From f04ef378c6b9478dd2e5291e8c621988787172e7 Mon Sep 17 00:00:00 2001 From: Emile Fugulin Date: Sat, 4 Dec 2021 12:05:24 -0500 Subject: [PATCH 01/36] Add feature to generate table Iden --- Cargo.toml | 1 + sea-orm-macros/Cargo.toml | 3 +++ sea-orm-macros/src/derives/column.rs | 5 +++++ sea-orm-macros/src/derives/entity_model.rs | 13 +++++++++++++ 4 files changed, 22 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index f73cfa51..27380d04 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,6 +67,7 @@ with-json = ["serde_json", "sea-query/with-json", "chrono/serde"] with-chrono = ["chrono", "sea-query/with-chrono"] with-rust_decimal = ["rust_decimal", "sea-query/with-rust_decimal"] with-uuid = ["uuid", "sea-query/with-uuid"] +with-table-iden = ["sea-orm-macros/with-table-iden"] sqlx-all = ["sqlx-mysql", "sqlx-postgres", "sqlx-sqlite"] sqlx-dep = ["sqlx-json", "sqlx-chrono", "sqlx-decimal", "sqlx-uuid"] sqlx-json = ["sqlx/json", "with-json"] diff --git a/sea-orm-macros/Cargo.toml b/sea-orm-macros/Cargo.toml index c4c82756..be22fb2f 100644 --- a/sea-orm-macros/Cargo.toml +++ b/sea-orm-macros/Cargo.toml @@ -25,3 +25,6 @@ proc-macro2 = "^1" [dev-dependencies] sea-orm = { path = "../", features = ["macros"] } serde = { version = "^1.0", features = ["derive"] } + +[features] +with-table-iden = [] diff --git a/sea-orm-macros/src/derives/column.rs b/sea-orm-macros/src/derives/column.rs index 8e60c560..97191250 100644 --- a/sea-orm-macros/src/derives/column.rs +++ b/sea-orm-macros/src/derives/column.rs @@ -45,6 +45,11 @@ pub fn impl_default_as_str(ident: &Ident, data: &Data) -> syn::Result) -> syn::Res } }); let entity_def = table_name + .clone() .map(|table_name| { quote! { #[derive(Copy, Clone, Default, Debug, sea_orm::prelude::DeriveEntity)] @@ -58,6 +59,18 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec) -> syn::Res let mut primary_keys: Punctuated<_, Comma> = Punctuated::new(); let mut primary_key_types: Punctuated<_, Comma> = Punctuated::new(); let mut auto_increment = true; + + #[cfg(feature = "with-table-iden")] + if let Some(table_name) = table_name { + let table_field_name = Ident::new("Table", Span::call_site()); + columns_enum.push(quote! { + #[sea_orm(table_name=#table_name)] + #[strum(disabled)] + #table_field_name + }); + columns_trait + .push(quote! { Self::#table_field_name => panic!("Table cannot be used as a column") }); + } if let Data::Struct(item_struct) = data { if let Fields::Named(fields) = item_struct.fields { for field in fields.named { From 90122374aa9e60e69d8d7672c91e04e915830529 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Tue, 7 Dec 2021 16:13:25 +0800 Subject: [PATCH 02/36] Add test cases [issues] --- .github/workflows/rust.yml | 2 +- issues/356/Cargo.toml | 11 ++++++++++ issues/356/src/main.rs | 3 +++ issues/356/src/model.rs | 42 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 issues/356/Cargo.toml create mode 100644 issues/356/src/main.rs create mode 100644 issues/356/src/model.rs diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index ab5d7663..4affff66 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -316,7 +316,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - path: [86, 249, 262, 319, 324, 352] + path: [86, 249, 262, 319, 324, 352, 356] steps: - uses: actions/checkout@v2 diff --git a/issues/356/Cargo.toml b/issues/356/Cargo.toml new file mode 100644 index 00000000..4e0e64d0 --- /dev/null +++ b/issues/356/Cargo.toml @@ -0,0 +1,11 @@ +[workspace] +# A separate workspace + +[package] +name = "sea-orm-issues-356" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +sea-orm = { path = "../../", features = [ "sqlx-mysql", "runtime-async-std-native-tls", "with-table-iden" ]} diff --git a/issues/356/src/main.rs b/issues/356/src/main.rs new file mode 100644 index 00000000..a9db43c3 --- /dev/null +++ b/issues/356/src/main.rs @@ -0,0 +1,3 @@ +mod model; + +pub fn main() {} diff --git a/issues/356/src/model.rs b/issues/356/src/model.rs new file mode 100644 index 00000000..44325a3a --- /dev/null +++ b/issues/356/src/model.rs @@ -0,0 +1,42 @@ +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "model")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub owner: String, + pub name: String, + pub description: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} + +#[cfg(test)] +mod tests { + use super::*; + use sea_orm::*; + + #[test] + fn test_columns_1() { + assert_eq!( + Column::iter() + .map(|col| col.to_string()) + .collect::>(), + vec![ + "id".to_owned(), + "owner".to_owned(), + "name".to_owned(), + "description".to_owned(), + ] + ); + assert_eq!(Column::Table.to_string().as_str(), "model"); + assert_eq!(Column::Id.to_string().as_str(), "id"); + assert_eq!(Column::Owner.to_string().as_str(), "owner"); + assert_eq!(Column::Name.to_string().as_str(), "name"); + assert_eq!(Column::Description.to_string().as_str(), "description"); + } +} From 2e26fa3873a75c9e7cebcbed25ea4f84341dc44d Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Tue, 7 Dec 2021 22:41:27 +0800 Subject: [PATCH 03/36] Fix clippy warnings --- sea-orm-macros/src/derives/entity_model.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sea-orm-macros/src/derives/entity_model.rs b/sea-orm-macros/src/derives/entity_model.rs index 3a54e145..e42957a2 100644 --- a/sea-orm-macros/src/derives/entity_model.rs +++ b/sea-orm-macros/src/derives/entity_model.rs @@ -33,7 +33,7 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec) -> syn::Res } }); let entity_def = table_name - .clone() + .as_ref() .map(|table_name| { quote! { #[derive(Copy, Clone, Default, Debug, sea_orm::prelude::DeriveEntity)] From 1aea3f6c6c9525f8056df5db3bac9f3bf8b7b844 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Wed, 8 Dec 2021 15:56:37 +0800 Subject: [PATCH 04/36] `Delete::many` with `TableRef` --- src/query/delete.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/query/delete.rs b/src/query/delete.rs index c7df0c7d..f85255df 100644 --- a/src/query/delete.rs +++ b/src/query/delete.rs @@ -3,7 +3,7 @@ use crate::{ QueryFilter, QueryTrait, }; use core::marker::PhantomData; -use sea_query::{DeleteStatement, IntoIden}; +use sea_query::DeleteStatement; /// Defines the structure for a delete operation #[derive(Clone, Debug)] @@ -94,7 +94,7 @@ impl Delete { { DeleteMany { query: DeleteStatement::new() - .from_table(entity.into_iden()) + .from_table(entity.table_ref()) .to_owned(), entity: PhantomData, } From aaec1bc8456aa2fd378864d16a5db08069a1f4cb Mon Sep 17 00:00:00 2001 From: Emile Fugulin Date: Wed, 8 Dec 2021 13:50:34 -0500 Subject: [PATCH 05/36] Use attribute instead of compilation flag --- Cargo.toml | 1 - issues/356/Cargo.toml | 2 +- issues/356/src/model.rs | 2 +- sea-orm-macros/Cargo.toml | 3 --- sea-orm-macros/src/attributes.rs | 1 + sea-orm-macros/src/derives/entity_model.rs | 30 ++++++++++++++-------- 6 files changed, 22 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 27380d04..f73cfa51 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,7 +67,6 @@ with-json = ["serde_json", "sea-query/with-json", "chrono/serde"] with-chrono = ["chrono", "sea-query/with-chrono"] with-rust_decimal = ["rust_decimal", "sea-query/with-rust_decimal"] with-uuid = ["uuid", "sea-query/with-uuid"] -with-table-iden = ["sea-orm-macros/with-table-iden"] sqlx-all = ["sqlx-mysql", "sqlx-postgres", "sqlx-sqlite"] sqlx-dep = ["sqlx-json", "sqlx-chrono", "sqlx-decimal", "sqlx-uuid"] sqlx-json = ["sqlx/json", "with-json"] diff --git a/issues/356/Cargo.toml b/issues/356/Cargo.toml index 4e0e64d0..ed64bae4 100644 --- a/issues/356/Cargo.toml +++ b/issues/356/Cargo.toml @@ -8,4 +8,4 @@ edition = "2021" publish = false [dependencies] -sea-orm = { path = "../../", features = [ "sqlx-mysql", "runtime-async-std-native-tls", "with-table-iden" ]} +sea-orm = { path = "../../", features = [ "sqlx-mysql", "runtime-async-std-native-tls" ]} diff --git a/issues/356/src/model.rs b/issues/356/src/model.rs index 44325a3a..912a3dcd 100644 --- a/issues/356/src/model.rs +++ b/issues/356/src/model.rs @@ -1,7 +1,7 @@ use sea_orm::entity::prelude::*; #[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "model")] +#[sea_orm(table_name = "model", table_iden)] pub struct Model { #[sea_orm(primary_key)] pub id: i32, diff --git a/sea-orm-macros/Cargo.toml b/sea-orm-macros/Cargo.toml index be22fb2f..c4c82756 100644 --- a/sea-orm-macros/Cargo.toml +++ b/sea-orm-macros/Cargo.toml @@ -25,6 +25,3 @@ proc-macro2 = "^1" [dev-dependencies] sea-orm = { path = "../", features = ["macros"] } serde = { version = "^1.0", features = ["derive"] } - -[features] -with-table-iden = [] diff --git a/sea-orm-macros/src/attributes.rs b/sea-orm-macros/src/attributes.rs index 3f479bb9..cb47d029 100644 --- a/sea-orm-macros/src/attributes.rs +++ b/sea-orm-macros/src/attributes.rs @@ -11,6 +11,7 @@ pub mod derive_attr { pub relation: Option, pub schema_name: Option, pub table_name: Option, + pub table_iden: Option<()>, } } diff --git a/sea-orm-macros/src/derives/entity_model.rs b/sea-orm-macros/src/derives/entity_model.rs index e42957a2..7309a6c4 100644 --- a/sea-orm-macros/src/derives/entity_model.rs +++ b/sea-orm-macros/src/derives/entity_model.rs @@ -12,6 +12,7 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec) -> syn::Res // if #[sea_orm(table_name = "foo", schema_name = "bar")] specified, create Entity struct let mut table_name = None; let mut schema_name = quote! { None }; + let mut table_iden = false; attrs.iter().for_each(|attr| { if attr.path.get_ident().map(|i| i == "sea_orm") != Some(true) { return; @@ -28,6 +29,12 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec) -> syn::Res schema_name = quote! { Some(#name) }; } } + } else if let Meta::Path(path) = meta { + if let Some(ident) = path.get_ident() { + if ident == "table_iden" { + table_iden = true; + } + } } } } @@ -59,17 +66,18 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec) -> syn::Res let mut primary_keys: Punctuated<_, Comma> = Punctuated::new(); let mut primary_key_types: Punctuated<_, Comma> = Punctuated::new(); let mut auto_increment = true; - - #[cfg(feature = "with-table-iden")] - if let Some(table_name) = table_name { - let table_field_name = Ident::new("Table", Span::call_site()); - columns_enum.push(quote! { - #[sea_orm(table_name=#table_name)] - #[strum(disabled)] - #table_field_name - }); - columns_trait - .push(quote! { Self::#table_field_name => panic!("Table cannot be used as a column") }); + if table_iden { + if let Some(table_name) = table_name { + let table_field_name = Ident::new("Table", Span::call_site()); + columns_enum.push(quote! { + #[sea_orm(table_name=#table_name)] + #[strum(disabled)] + #table_field_name + }); + columns_trait.push( + quote! { Self::#table_field_name => panic!("Table cannot be used as a column") }, + ); + } } if let Data::Struct(item_struct) = data { if let Fields::Named(fields) = item_struct.fields { From 6b94673dd9869955342a46468c61160f392bdc0e Mon Sep 17 00:00:00 2001 From: Marco Napetti Date: Thu, 9 Dec 2021 15:12:41 +0100 Subject: [PATCH 06/36] First metric and tracing implementation --- Cargo.toml | 11 ++-- src/database/db_connection.rs | 8 +++ src/database/mock.rs | 6 ++ src/database/mod.rs | 2 + src/database/stream/query.rs | 92 ++++++++++++++++++++---------- src/database/stream/transaction.rs | 45 ++++++++++++--- src/database/transaction.rs | 45 ++++++++++++++- src/driver/mock.rs | 9 +++ src/driver/sqlx_mysql.rs | 41 ++++++++++++- src/driver/sqlx_postgres.rs | 41 ++++++++++++- src/driver/sqlx_sqlite.rs | 41 ++++++++++++- src/lib.rs | 2 + src/metric.rs | 28 +++++++++ src/util.rs | 2 +- 14 files changed, 317 insertions(+), 56 deletions(-) create mode 100644 src/metric.rs diff --git a/Cargo.toml b/Cargo.toml index 47f075eb..240bd053 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ async-trait = { version = "^0.1" } chrono = { version = "^0", optional = true } futures = { version = "^0.3" } futures-util = { version = "^0.3" } -log = { version = "^0.4", optional = true } +tracing = "0.1" rust_decimal = { version = "^1", optional = true } sea-orm-macros = { version = "^0.4.1", path = "sea-orm-macros", optional = true } sea-query = { version = "^0.19.1", features = ["thread-safe"] } @@ -36,8 +36,9 @@ serde = { version = "^1.0", features = ["derive"] } serde_json = { version = "^1", optional = true } sqlx = { version = "^0.5", optional = true } uuid = { version = "0.8", features = ["serde", "v4"], optional = true } -ouroboros = "0.11" +ouroboros = "0.14" url = "^2.2" +once_cell = "1.8" [dev-dependencies] smol = { version = "^1.2" } @@ -47,12 +48,12 @@ tokio = { version = "^1.6", features = ["full"] } actix-rt = { version = "2.2.0" } maplit = { version = "^1" } rust_decimal_macros = { version = "^1" } -env_logger = { version = "^0.9" } +tracing-subscriber = { version = "0.3", features = ["env-filter"] } sea-orm = { path = ".", features = ["debug-print"] } pretty_assertions = { version = "^0.7" } [features] -debug-print = ["log"] +debug-print = [] default = [ "macros", "mock", @@ -60,6 +61,8 @@ default = [ "with-chrono", "with-rust_decimal", "with-uuid", + "runtime-tokio-rustls",#debug + "sqlx-all",#debug ] macros = ["sea-orm-macros"] mock = [] diff --git a/src/database/db_connection.rs b/src/database/db_connection.rs index 99de8633..b9249d99 100644 --- a/src/database/db_connection.rs +++ b/src/database/db_connection.rs @@ -3,6 +3,7 @@ use crate::{ StatementBuilder, TransactionError, }; use sea_query::{MysqlQueryBuilder, PostgresQueryBuilder, QueryBuilder, SqliteQueryBuilder}; +use tracing::instrument; use std::{future::Future, pin::Pin}; use url::Url; @@ -49,6 +50,7 @@ pub enum DatabaseBackend { /// The same as [DatabaseBackend] just shorter :) pub type DbBackend = DatabaseBackend; +#[derive(Debug)] pub(crate) enum InnerConnection { #[cfg(feature = "sqlx-mysql")] MySql(PoolConnection), @@ -104,6 +106,7 @@ impl<'a> ConnectionTrait<'a> for DatabaseConnection { } } + #[instrument(level = "trace")] async fn execute(&self, stmt: Statement) -> Result { match self { #[cfg(feature = "sqlx-mysql")] @@ -118,6 +121,7 @@ impl<'a> ConnectionTrait<'a> for DatabaseConnection { } } + #[instrument(level = "trace")] async fn query_one(&self, stmt: Statement) -> Result, DbErr> { match self { #[cfg(feature = "sqlx-mysql")] @@ -132,6 +136,7 @@ impl<'a> ConnectionTrait<'a> for DatabaseConnection { } } + #[instrument(level = "trace")] async fn query_all(&self, stmt: Statement) -> Result, DbErr> { match self { #[cfg(feature = "sqlx-mysql")] @@ -146,6 +151,7 @@ impl<'a> ConnectionTrait<'a> for DatabaseConnection { } } + #[instrument(level = "trace")] fn stream( &'a self, stmt: Statement, @@ -167,6 +173,7 @@ impl<'a> ConnectionTrait<'a> for DatabaseConnection { }) } + #[instrument(level = "trace")] async fn begin(&self) -> Result { match self { #[cfg(feature = "sqlx-mysql")] @@ -185,6 +192,7 @@ impl<'a> ConnectionTrait<'a> for DatabaseConnection { /// Execute the function inside a transaction. /// If the function returns an error, the transaction will be rolled back. If it does not return an error, the transaction will be committed. + #[instrument(level = "trace", skip(_callback))] async fn transaction(&self, _callback: F) -> Result> where F: for<'c> FnOnce( diff --git a/src/database/mock.rs b/src/database/mock.rs index 74ffd8bf..b3ae74fc 100644 --- a/src/database/mock.rs +++ b/src/database/mock.rs @@ -4,6 +4,7 @@ use crate::{ Statement, }; use sea_query::{Value, ValueType, Values}; +use tracing::instrument; use std::{collections::BTreeMap, sync::Arc}; /// Defines a Mock database suitable for testing @@ -89,6 +90,7 @@ impl MockDatabase { } impl MockDatabaseTrait for MockDatabase { + #[instrument(level = "trace")] fn execute(&mut self, counter: usize, statement: Statement) -> Result { if let Some(transaction) = &mut self.transaction { transaction.push(statement); @@ -104,6 +106,7 @@ impl MockDatabaseTrait for MockDatabase { } } + #[instrument(level = "trace")] fn query(&mut self, counter: usize, statement: Statement) -> Result, DbErr> { if let Some(transaction) = &mut self.transaction { transaction.push(statement); @@ -122,6 +125,7 @@ impl MockDatabaseTrait for MockDatabase { } } + #[instrument(level = "trace")] fn begin(&mut self) { if self.transaction.is_some() { self.transaction @@ -133,6 +137,7 @@ impl MockDatabaseTrait for MockDatabase { } } + #[instrument(level = "trace")] fn commit(&mut self) { if self.transaction.is_some() { if self.transaction.as_mut().unwrap().commit(self.db_backend) { @@ -144,6 +149,7 @@ impl MockDatabaseTrait for MockDatabase { } } + #[instrument(level = "trace")] fn rollback(&mut self) { if self.transaction.is_some() { if self.transaction.as_mut().unwrap().rollback(self.db_backend) { diff --git a/src/database/mod.rs b/src/database/mod.rs index 28bdbb78..1a9556c7 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -14,6 +14,7 @@ pub use db_connection::*; pub use mock::*; pub use statement::*; pub use stream::*; +use tracing::instrument; pub use transaction::*; use crate::DbErr; @@ -42,6 +43,7 @@ pub struct ConnectOptions { impl Database { /// Method to create a [DatabaseConnection] on a database + #[instrument(level = "trace", skip(opt))] pub async fn connect(opt: C) -> Result where C: Into, diff --git a/src/database/stream/query.rs b/src/database/stream/query.rs index c2c88d0d..144a6b83 100644 --- a/src/database/stream/query.rs +++ b/src/database/stream/query.rs @@ -12,6 +12,8 @@ use futures::TryStreamExt; #[cfg(feature = "sqlx-dep")] use sqlx::{pool::PoolConnection, Executor}; +use tracing::instrument; + use crate::{DbErr, InnerConnection, QueryResult, Statement}; /// Creates a stream from a [QueryResult] @@ -59,41 +61,71 @@ impl std::fmt::Debug for QueryStream { } impl QueryStream { + #[instrument(level = "trace")] fn build(stmt: Statement, conn: InnerConnection) -> QueryStream { QueryStreamBuilder { stmt, conn, - stream_builder: |conn, stmt| match conn { - #[cfg(feature = "sqlx-mysql")] - InnerConnection::MySql(c) => { - let query = crate::driver::sqlx_mysql::sqlx_query(stmt); - Box::pin( - c.fetch(query) - .map_ok(Into::into) - .map_err(crate::sqlx_error_to_query_err), - ) + stream_builder: |conn, stmt| { + match conn { + #[cfg(feature = "sqlx-mysql")] + InnerConnection::MySql(c) => { + let query = crate::driver::sqlx_mysql::sqlx_query(stmt); + let _start = std::time::SystemTime::now(); + let res = Box::pin( + c.fetch(query) + .map_ok(Into::into) + .map_err(crate::sqlx_error_to_query_err), + ); + if let Some(callback) = crate::metric::get_callback() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: stmt, + }; + callback(&info); + } + res + } + #[cfg(feature = "sqlx-postgres")] + InnerConnection::Postgres(c) => { + let query = crate::driver::sqlx_postgres::sqlx_query(stmt); + let _start = std::time::SystemTime::now(); + let res = Box::pin( + c.fetch(query) + .map_ok(Into::into) + .map_err(crate::sqlx_error_to_query_err), + ); + if let Some(callback) = crate::metric::get_callback() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: stmt, + }; + callback(&info); + } + res + } + #[cfg(feature = "sqlx-sqlite")] + InnerConnection::Sqlite(c) => { + let query = crate::driver::sqlx_sqlite::sqlx_query(stmt); + let _start = std::time::SystemTime::now(); + let res = Box::pin( + c.fetch(query) + .map_ok(Into::into) + .map_err(crate::sqlx_error_to_query_err), + ); + if let Some(callback) = crate::metric::get_callback() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: stmt, + }; + callback(&info); + } + res + } + #[cfg(feature = "mock")] + InnerConnection::Mock(c) => c.fetch(stmt), } - #[cfg(feature = "sqlx-postgres")] - InnerConnection::Postgres(c) => { - let query = crate::driver::sqlx_postgres::sqlx_query(stmt); - Box::pin( - c.fetch(query) - .map_ok(Into::into) - .map_err(crate::sqlx_error_to_query_err), - ) - } - #[cfg(feature = "sqlx-sqlite")] - InnerConnection::Sqlite(c) => { - let query = crate::driver::sqlx_sqlite::sqlx_query(stmt); - Box::pin( - c.fetch(query) - .map_ok(Into::into) - .map_err(crate::sqlx_error_to_query_err), - ) - } - #[cfg(feature = "mock")] - InnerConnection::Mock(c) => c.fetch(stmt), - }, + } } .build() } diff --git a/src/database/stream/transaction.rs b/src/database/stream/transaction.rs index 77a59819..d2643f63 100644 --- a/src/database/stream/transaction.rs +++ b/src/database/stream/transaction.rs @@ -11,6 +11,8 @@ use sqlx::Executor; use futures::lock::MutexGuard; +use tracing::instrument; + use crate::{DbErr, InnerConnection, QueryResult, Statement}; /// `TransactionStream` cannot be used in a `transaction` closure as it does not impl `Send`. @@ -31,6 +33,7 @@ impl<'a> std::fmt::Debug for TransactionStream<'a> { } impl<'a> TransactionStream<'a> { + #[instrument(level = "trace")] pub(crate) async fn build( conn: MutexGuard<'a, InnerConnection>, stmt: Statement, @@ -44,32 +47,56 @@ impl<'a> TransactionStream<'a> { #[cfg(feature = "sqlx-mysql")] InnerConnection::MySql(c) => { let query = crate::driver::sqlx_mysql::sqlx_query(stmt); - Box::pin( + let _start = std::time::SystemTime::now(); + let res = Box::pin( c.fetch(query) .map_ok(Into::into) .map_err(crate::sqlx_error_to_query_err), - ) - as Pin>>> + ) as Pin>>>; + if let Some(callback) = crate::metric::get_callback() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: stmt, + }; + callback(&info); + } + res } #[cfg(feature = "sqlx-postgres")] InnerConnection::Postgres(c) => { let query = crate::driver::sqlx_postgres::sqlx_query(stmt); - Box::pin( + let _start = std::time::SystemTime::now(); + let res = Box::pin( c.fetch(query) .map_ok(Into::into) .map_err(crate::sqlx_error_to_query_err), - ) - as Pin>>> + ) as Pin>>>; + if let Some(callback) = crate::metric::get_callback() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: stmt, + }; + callback(&info); + } + res } #[cfg(feature = "sqlx-sqlite")] InnerConnection::Sqlite(c) => { let query = crate::driver::sqlx_sqlite::sqlx_query(stmt); - Box::pin( + let _start = std::time::SystemTime::now(); + let res = Box::pin( c.fetch(query) .map_ok(Into::into) .map_err(crate::sqlx_error_to_query_err), - ) - as Pin>>> + ) as Pin>>>; + if let Some(callback) = crate::metric::get_callback() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: stmt, + }; + callback(&info); + } + res } #[cfg(feature = "mock")] InnerConnection::Mock(c) => c.fetch(stmt), diff --git a/src/database/transaction.rs b/src/database/transaction.rs index f4a1b678..e26067db 100644 --- a/src/database/transaction.rs +++ b/src/database/transaction.rs @@ -7,6 +7,7 @@ use crate::{sqlx_error_to_exec_err, sqlx_error_to_query_err}; use futures::lock::Mutex; #[cfg(feature = "sqlx-dep")] use sqlx::{pool::PoolConnection, TransactionManager}; +use tracing::instrument; use std::{future::Future, pin::Pin, sync::Arc}; // a Transaction is just a sugar for a connection where START TRANSACTION has been executed @@ -66,6 +67,7 @@ impl DatabaseTransaction { Self::begin(Arc::new(Mutex::new(InnerConnection::Mock(inner))), backend).await } + #[instrument(level = "trace")] async fn begin( conn: Arc>, backend: DbBackend, @@ -104,6 +106,7 @@ impl DatabaseTransaction { /// Runs a transaction to completion returning an rolling back the transaction on /// encountering an error if it fails + #[instrument(level = "trace", skip(callback))] pub(crate) async fn run(self, callback: F) -> Result> where F: for<'b> FnOnce( @@ -125,6 +128,7 @@ impl DatabaseTransaction { } /// Commit a transaction atomically + #[instrument(level = "trace")] pub async fn commit(mut self) -> Result<(), DbErr> { self.open = false; match *self.conn.lock().await { @@ -155,6 +159,7 @@ impl DatabaseTransaction { } /// rolls back a transaction in case error are encountered during the operation + #[instrument(level = "trace")] pub async fn rollback(mut self) -> Result<(), DbErr> { self.open = false; match *self.conn.lock().await { @@ -185,6 +190,7 @@ impl DatabaseTransaction { } // the rollback is queued and will be performed on next async operation, like returning the connection to the pool + #[instrument(level = "trace")] fn start_rollback(&mut self) { if self.open { if let Some(mut conn) = self.conn.try_lock() { @@ -229,6 +235,7 @@ impl<'a> ConnectionTrait<'a> for DatabaseTransaction { self.backend } + #[instrument(level = "trace")] async fn execute(&self, stmt: Statement) -> Result { debug_print!("{}", stmt); @@ -236,17 +243,44 @@ impl<'a> ConnectionTrait<'a> for DatabaseTransaction { #[cfg(feature = "sqlx-mysql")] InnerConnection::MySql(conn) => { let query = crate::driver::sqlx_mysql::sqlx_query(&stmt); - query.execute(conn).await.map(Into::into) + let _start = std::time::SystemTime::now(); + let res = query.execute(conn).await.map(Into::into); + if let Some(callback) = crate::metric::get_callback() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: &stmt, + }; + callback(&info); + } + res } #[cfg(feature = "sqlx-postgres")] InnerConnection::Postgres(conn) => { let query = crate::driver::sqlx_postgres::sqlx_query(&stmt); - query.execute(conn).await.map(Into::into) + let _start = std::time::SystemTime::now(); + let res = query.execute(conn).await.map(Into::into); + if let Some(callback) = crate::metric::get_callback() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: &stmt, + }; + callback(&info); + } + res } #[cfg(feature = "sqlx-sqlite")] InnerConnection::Sqlite(conn) => { let query = crate::driver::sqlx_sqlite::sqlx_query(&stmt); - query.execute(conn).await.map(Into::into) + let _start = std::time::SystemTime::now(); + let res = query.execute(conn).await.map(Into::into); + if let Some(callback) = crate::metric::get_callback() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: &stmt, + }; + callback(&info); + } + res } #[cfg(feature = "mock")] InnerConnection::Mock(conn) => return conn.execute(stmt), @@ -255,6 +289,7 @@ impl<'a> ConnectionTrait<'a> for DatabaseTransaction { _res.map_err(sqlx_error_to_exec_err) } + #[instrument(level = "trace")] async fn query_one(&self, stmt: Statement) -> Result, DbErr> { debug_print!("{}", stmt); @@ -285,6 +320,7 @@ impl<'a> ConnectionTrait<'a> for DatabaseTransaction { } } + #[instrument(level = "trace")] async fn query_all(&self, stmt: Statement) -> Result, DbErr> { debug_print!("{}", stmt); @@ -320,6 +356,7 @@ impl<'a> ConnectionTrait<'a> for DatabaseTransaction { _res.map_err(sqlx_error_to_query_err) } + #[instrument(level = "trace")] fn stream( &'a self, stmt: Statement, @@ -329,12 +366,14 @@ impl<'a> ConnectionTrait<'a> for DatabaseTransaction { ) } + #[instrument(level = "trace")] async fn begin(&self) -> Result { DatabaseTransaction::begin(Arc::clone(&self.conn), self.backend).await } /// Execute the function inside a transaction. /// If the function returns an error, the transaction will be rolled back. If it does not return an error, the transaction will be committed. + #[instrument(level = "trace", skip(_callback))] async fn transaction(&self, _callback: F) -> Result> where F: for<'c> FnOnce( diff --git a/src/driver/mock.rs b/src/driver/mock.rs index cdded50c..12f3cc5c 100644 --- a/src/driver/mock.rs +++ b/src/driver/mock.rs @@ -3,6 +3,7 @@ use crate::{ Statement, Transaction, }; use futures::Stream; +use tracing::instrument; use std::{ fmt::Debug, pin::Pin, @@ -69,6 +70,7 @@ impl MockDatabaseConnector { /// Cpnnect to the [MockDatabase] #[allow(unused_variables)] + #[instrument(level = "trace")] pub async fn connect(string: &str) -> Result { macro_rules! connect_mock_db { ( $syntax: expr ) => { @@ -117,6 +119,7 @@ impl MockDatabaseConnection { } /// Execute the SQL statement in the [MockDatabase] + #[instrument(level = "trace")] pub fn execute(&self, statement: Statement) -> Result { debug_print!("{}", statement); let counter = self.execute_counter.fetch_add(1, Ordering::SeqCst); @@ -124,6 +127,7 @@ impl MockDatabaseConnection { } /// Return one [QueryResult] if the query was successful + #[instrument(level = "trace")] pub fn query_one(&self, statement: Statement) -> Result, DbErr> { debug_print!("{}", statement); let counter = self.query_counter.fetch_add(1, Ordering::SeqCst); @@ -132,6 +136,7 @@ impl MockDatabaseConnection { } /// Return all [QueryResult]s if the query was successful + #[instrument(level = "trace")] pub fn query_all(&self, statement: Statement) -> Result, DbErr> { debug_print!("{}", statement); let counter = self.query_counter.fetch_add(1, Ordering::SeqCst); @@ -139,6 +144,7 @@ impl MockDatabaseConnection { } /// Return [QueryResult]s from a multi-query operation + #[instrument(level = "trace")] pub fn fetch( &self, statement: &Statement, @@ -150,16 +156,19 @@ impl MockDatabaseConnection { } /// Create a statement block of SQL statements that execute together. + #[instrument(level = "trace")] pub fn begin(&self) { self.mocker.lock().unwrap().begin() } /// Commit a transaction atomically to the database + #[instrument(level = "trace")] pub fn commit(&self) { self.mocker.lock().unwrap().commit() } /// Roll back a faulty transaction + #[instrument(level = "trace")] pub fn rollback(&self) { self.mocker.lock().unwrap().rollback() } diff --git a/src/driver/sqlx_mysql.rs b/src/driver/sqlx_mysql.rs index 3f9936e4..2b2efd68 100644 --- a/src/driver/sqlx_mysql.rs +++ b/src/driver/sqlx_mysql.rs @@ -7,6 +7,7 @@ use sqlx::{ sea_query::sea_query_driver_mysql!(); use sea_query_driver_mysql::bind_query; +use tracing::instrument; use crate::{ debug_print, error::*, executor::*, ConnectOptions, DatabaseConnection, DatabaseTransaction, @@ -32,6 +33,7 @@ impl SqlxMySqlConnector { } /// Add configuration options for the MySQL database + #[instrument(level = "trace")] pub async fn connect(options: ConnectOptions) -> Result { let mut opt = options .url @@ -59,15 +61,25 @@ impl SqlxMySqlConnector { impl SqlxMySqlPoolConnection { /// Execute a [Statement] on a MySQL backend + #[instrument(level = "trace")] pub async fn execute(&self, stmt: Statement) -> Result { debug_print!("{}", stmt); let query = sqlx_query(&stmt); if let Ok(conn) = &mut self.pool.acquire().await { - match query.execute(conn).await { + let _start = std::time::SystemTime::now(); + let res = match query.execute(conn).await { Ok(res) => Ok(res.into()), Err(err) => Err(sqlx_error_to_exec_err(err)), + }; + if let Some(callback) = crate::metric::get_callback() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: &stmt, + }; + callback(&info); } + res } else { Err(DbErr::Exec( "Failed to acquire connection from pool.".to_owned(), @@ -76,18 +88,28 @@ impl SqlxMySqlPoolConnection { } /// Get one result from a SQL query. Returns [Option::None] if no match was found + #[instrument(level = "trace")] pub async fn query_one(&self, stmt: Statement) -> Result, DbErr> { debug_print!("{}", stmt); let query = sqlx_query(&stmt); if let Ok(conn) = &mut self.pool.acquire().await { - match query.fetch_one(conn).await { + let _start = std::time::SystemTime::now(); + let res = match query.fetch_one(conn).await { Ok(row) => Ok(Some(row.into())), Err(err) => match err { sqlx::Error::RowNotFound => Ok(None), _ => Err(DbErr::Query(err.to_string())), }, + }; + if let Some(callback) = crate::metric::get_callback() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: &stmt, + }; + callback(&info); } + res } else { Err(DbErr::Query( "Failed to acquire connection from pool.".to_owned(), @@ -96,15 +118,25 @@ impl SqlxMySqlPoolConnection { } /// Get the results of a query returning them as a Vec<[QueryResult]> + #[instrument(level = "trace")] pub async fn query_all(&self, stmt: Statement) -> Result, DbErr> { debug_print!("{}", stmt); let query = sqlx_query(&stmt); if let Ok(conn) = &mut self.pool.acquire().await { - match query.fetch_all(conn).await { + let _start = std::time::SystemTime::now(); + let res = match query.fetch_all(conn).await { Ok(rows) => Ok(rows.into_iter().map(|r| r.into()).collect()), Err(err) => Err(sqlx_error_to_query_err(err)), + }; + if let Some(callback) = crate::metric::get_callback() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: &stmt, + }; + callback(&info); } + res } else { Err(DbErr::Query( "Failed to acquire connection from pool.".to_owned(), @@ -113,6 +145,7 @@ impl SqlxMySqlPoolConnection { } /// Stream the results of executing a SQL query + #[instrument(level = "trace")] pub async fn stream(&self, stmt: Statement) -> Result { debug_print!("{}", stmt); @@ -126,6 +159,7 @@ impl SqlxMySqlPoolConnection { } /// Bundle a set of SQL statements that execute together. + #[instrument(level = "trace")] pub async fn begin(&self) -> Result { if let Ok(conn) = self.pool.acquire().await { DatabaseTransaction::new_mysql(conn).await @@ -137,6 +171,7 @@ impl SqlxMySqlPoolConnection { } /// Create a MySQL transaction + #[instrument(level = "trace", skip(callback))] 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 3abebe31..121e4e72 100644 --- a/src/driver/sqlx_postgres.rs +++ b/src/driver/sqlx_postgres.rs @@ -7,6 +7,7 @@ use sqlx::{ sea_query::sea_query_driver_postgres!(); use sea_query_driver_postgres::bind_query; +use tracing::instrument; use crate::{ debug_print, error::*, executor::*, ConnectOptions, DatabaseConnection, DatabaseTransaction, @@ -32,6 +33,7 @@ impl SqlxPostgresConnector { } /// Add configuration options for the MySQL database + #[instrument(level = "trace")] pub async fn connect(options: ConnectOptions) -> Result { let mut opt = options .url @@ -59,15 +61,25 @@ impl SqlxPostgresConnector { impl SqlxPostgresPoolConnection { /// Execute a [Statement] on a PostgreSQL backend + #[instrument(level = "trace")] pub async fn execute(&self, stmt: Statement) -> Result { debug_print!("{}", stmt); let query = sqlx_query(&stmt); if let Ok(conn) = &mut self.pool.acquire().await { - match query.execute(conn).await { + let _start = std::time::SystemTime::now(); + let res = match query.execute(conn).await { Ok(res) => Ok(res.into()), Err(err) => Err(sqlx_error_to_exec_err(err)), + }; + if let Some(callback) = crate::metric::get_callback() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: &stmt, + }; + callback(&info); } + res } else { Err(DbErr::Exec( "Failed to acquire connection from pool.".to_owned(), @@ -76,18 +88,28 @@ impl SqlxPostgresPoolConnection { } /// Get one result from a SQL query. Returns [Option::None] if no match was found + #[instrument(level = "trace")] pub async fn query_one(&self, stmt: Statement) -> Result, DbErr> { debug_print!("{}", stmt); let query = sqlx_query(&stmt); if let Ok(conn) = &mut self.pool.acquire().await { - match query.fetch_one(conn).await { + let _start = std::time::SystemTime::now(); + let res = match query.fetch_one(conn).await { Ok(row) => Ok(Some(row.into())), Err(err) => match err { sqlx::Error::RowNotFound => Ok(None), _ => Err(DbErr::Query(err.to_string())), }, + }; + if let Some(callback) = crate::metric::get_callback() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: &stmt, + }; + callback(&info); } + res } else { Err(DbErr::Query( "Failed to acquire connection from pool.".to_owned(), @@ -96,15 +118,25 @@ impl SqlxPostgresPoolConnection { } /// Get the results of a query returning them as a Vec<[QueryResult]> + #[instrument(level = "trace")] pub async fn query_all(&self, stmt: Statement) -> Result, DbErr> { debug_print!("{}", stmt); let query = sqlx_query(&stmt); if let Ok(conn) = &mut self.pool.acquire().await { - match query.fetch_all(conn).await { + let _start = std::time::SystemTime::now(); + let res = match query.fetch_all(conn).await { Ok(rows) => Ok(rows.into_iter().map(|r| r.into()).collect()), Err(err) => Err(sqlx_error_to_query_err(err)), + }; + if let Some(callback) = crate::metric::get_callback() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: &stmt, + }; + callback(&info); } + res } else { Err(DbErr::Query( "Failed to acquire connection from pool.".to_owned(), @@ -113,6 +145,7 @@ impl SqlxPostgresPoolConnection { } /// Stream the results of executing a SQL query + #[instrument(level = "trace")] pub async fn stream(&self, stmt: Statement) -> Result { debug_print!("{}", stmt); @@ -126,6 +159,7 @@ impl SqlxPostgresPoolConnection { } /// Bundle a set of SQL statements that execute together. + #[instrument(level = "trace")] pub async fn begin(&self) -> Result { if let Ok(conn) = self.pool.acquire().await { DatabaseTransaction::new_postgres(conn).await @@ -137,6 +171,7 @@ impl SqlxPostgresPoolConnection { } /// Create a PostgreSQL transaction + #[instrument(level = "trace", skip(callback))] 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 255686d2..9cfd9a72 100644 --- a/src/driver/sqlx_sqlite.rs +++ b/src/driver/sqlx_sqlite.rs @@ -7,6 +7,7 @@ use sqlx::{ sea_query::sea_query_driver_sqlite!(); use sea_query_driver_sqlite::bind_query; +use tracing::instrument; use crate::{ debug_print, error::*, executor::*, ConnectOptions, DatabaseConnection, DatabaseTransaction, @@ -32,6 +33,7 @@ impl SqlxSqliteConnector { } /// Add configuration options for the SQLite database + #[instrument(level = "trace")] pub async fn connect(options: ConnectOptions) -> Result { let mut options = options; let mut opt = options @@ -63,15 +65,25 @@ impl SqlxSqliteConnector { impl SqlxSqlitePoolConnection { /// Execute a [Statement] on a SQLite backend + #[instrument(level = "trace")] pub async fn execute(&self, stmt: Statement) -> Result { debug_print!("{}", stmt); let query = sqlx_query(&stmt); if let Ok(conn) = &mut self.pool.acquire().await { - match query.execute(conn).await { + let _start = std::time::SystemTime::now(); + let res = match query.execute(conn).await { Ok(res) => Ok(res.into()), Err(err) => Err(sqlx_error_to_exec_err(err)), + }; + if let Some(callback) = crate::metric::get_callback() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: &stmt, + }; + callback(&info); } + res } else { Err(DbErr::Exec( "Failed to acquire connection from pool.".to_owned(), @@ -80,18 +92,28 @@ impl SqlxSqlitePoolConnection { } /// Get one result from a SQL query. Returns [Option::None] if no match was found + #[instrument(level = "trace")] pub async fn query_one(&self, stmt: Statement) -> Result, DbErr> { debug_print!("{}", stmt); let query = sqlx_query(&stmt); if let Ok(conn) = &mut self.pool.acquire().await { - match query.fetch_one(conn).await { + let _start = std::time::SystemTime::now(); + let res = match query.fetch_one(conn).await { Ok(row) => Ok(Some(row.into())), Err(err) => match err { sqlx::Error::RowNotFound => Ok(None), _ => Err(DbErr::Query(err.to_string())), }, + }; + if let Some(callback) = crate::metric::get_callback() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: &stmt, + }; + callback(&info); } + res } else { Err(DbErr::Query( "Failed to acquire connection from pool.".to_owned(), @@ -100,15 +122,25 @@ impl SqlxSqlitePoolConnection { } /// Get the results of a query returning them as a Vec<[QueryResult]> + #[instrument(level = "trace")] pub async fn query_all(&self, stmt: Statement) -> Result, DbErr> { debug_print!("{}", stmt); let query = sqlx_query(&stmt); if let Ok(conn) = &mut self.pool.acquire().await { - match query.fetch_all(conn).await { + let _start = std::time::SystemTime::now(); + let res = match query.fetch_all(conn).await { Ok(rows) => Ok(rows.into_iter().map(|r| r.into()).collect()), Err(err) => Err(sqlx_error_to_query_err(err)), + }; + if let Some(callback) = crate::metric::get_callback() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: &stmt, + }; + callback(&info); } + res } else { Err(DbErr::Query( "Failed to acquire connection from pool.".to_owned(), @@ -117,6 +149,7 @@ impl SqlxSqlitePoolConnection { } /// Stream the results of executing a SQL query + #[instrument(level = "trace")] pub async fn stream(&self, stmt: Statement) -> Result { debug_print!("{}", stmt); @@ -130,6 +163,7 @@ impl SqlxSqlitePoolConnection { } /// Bundle a set of SQL statements that execute together. + #[instrument(level = "trace")] pub async fn begin(&self) -> Result { if let Ok(conn) = self.pool.acquire().await { DatabaseTransaction::new_sqlite(conn).await @@ -141,6 +175,7 @@ impl SqlxSqlitePoolConnection { } /// Create a MySQL transaction + #[instrument(level = "trace", skip(callback))] pub async fn transaction(&self, callback: F) -> Result> where F: for<'b> FnOnce( diff --git a/src/lib.rs b/src/lib.rs index 469619f0..5b6787dc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -284,6 +284,8 @@ pub mod schema; #[cfg(feature = "macros")] pub mod tests_cfg; mod util; +/// Holds types and methods to perform metric collection +pub mod metric; pub use database::*; pub use driver::*; diff --git a/src/metric.rs b/src/metric.rs new file mode 100644 index 00000000..4eab0e74 --- /dev/null +++ b/src/metric.rs @@ -0,0 +1,28 @@ +use std::time::Duration; + +use once_cell::sync::OnceCell; + +type Callback = Box) + Send + Sync>; + +static METRIC: OnceCell = OnceCell::new(); + +#[derive(Debug)] +/// Query execution infos +pub struct Info<'a> { + /// Query executiuon duration + pub elapsed: Duration, + /// Query data + pub statement: &'a crate::Statement, +} + +/// Sets a new metric callback, returning it if already set +pub fn set_callback(callback: F) -> Result<(), Callback> +where + F: Fn(&Info<'_>) + Send + Sync + 'static, +{ + METRIC.set(Box::new(callback)) +} + +pub(crate) fn get_callback() -> Option<&'static Callback> { + METRIC.get() +} diff --git a/src/util.rs b/src/util.rs index 9ffa1e4c..f8614099 100644 --- a/src/util.rs +++ b/src/util.rs @@ -15,7 +15,7 @@ #[macro_export] #[cfg(feature = "debug-print")] macro_rules! debug_print { - ($( $args:expr ),*) => { log::debug!( $( $args ),* ); } + ($( $args:expr ),*) => { tracing::debug!( $( $args ),* ); } } #[macro_export] From 8ad9781a3f8b4285719bc2b012fc9ed9c7272d47 Mon Sep 17 00:00:00 2001 From: Marco Napetti Date: Thu, 9 Dec 2021 16:20:53 +0100 Subject: [PATCH 07/36] Remove debug features --- Cargo.toml | 2 -- sea-orm-macros/src/lib.rs | 5 ++--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 240bd053..7b3bcdfb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,8 +61,6 @@ default = [ "with-chrono", "with-rust_decimal", "with-uuid", - "runtime-tokio-rustls",#debug - "sqlx-all",#debug ] macros = ["sea-orm-macros"] mock = [] diff --git a/sea-orm-macros/src/lib.rs b/sea-orm-macros/src/lib.rs index 00540aa4..7fc4b3d0 100644 --- a/sea-orm-macros/src/lib.rs +++ b/sea-orm-macros/src/lib.rs @@ -596,9 +596,8 @@ pub fn test(_: TokenStream, input: TokenStream) -> TokenStream { #[test] #(#attrs)* fn #name() #ret { - let _ = ::env_logger::builder() - .filter_level(::log::LevelFilter::Debug) - .is_test(true) + let _ = ::tracing_subscriber::fmt() + .with_max_level(::tracing::Level::DEBUG) .try_init(); crate::block_on!(async { #body }) } From 4abe8310a57e5cbf7a52e9e32b614cd0aad48fd5 Mon Sep 17 00:00:00 2001 From: Marco Napetti Date: Thu, 9 Dec 2021 19:03:46 +0100 Subject: [PATCH 08/36] Per-connection metric --- src/database/db_connection.rs | 24 +++++++++++++++--- src/database/stream/query.rs | 40 ++++++++++++++++-------------- src/database/stream/transaction.rs | 15 ++++++----- src/database/transaction.rs | 32 ++++++++++++++++++------ src/driver/sqlx_mysql.rs | 32 +++++++++++++++++------- src/driver/sqlx_postgres.rs | 32 +++++++++++++++++------- src/driver/sqlx_sqlite.rs | 32 +++++++++++++++++------- src/metric.rs | 20 ++------------- 8 files changed, 147 insertions(+), 80 deletions(-) diff --git a/src/database/db_connection.rs b/src/database/db_connection.rs index b9249d99..3a090b6f 100644 --- a/src/database/db_connection.rs +++ b/src/database/db_connection.rs @@ -166,7 +166,7 @@ impl<'a> ConnectionTrait<'a> for DatabaseConnection { DatabaseConnection::SqlxSqlitePoolConnection(conn) => conn.stream(stmt).await?, #[cfg(feature = "mock")] DatabaseConnection::MockDatabaseConnection(conn) => { - crate::QueryStream::from((Arc::clone(conn), stmt)) + crate::QueryStream::from((Arc::clone(conn), stmt, None)) } DatabaseConnection::Disconnected => panic!("Disconnected"), }) @@ -184,7 +184,7 @@ impl<'a> ConnectionTrait<'a> for DatabaseConnection { DatabaseConnection::SqlxSqlitePoolConnection(conn) => conn.begin().await, #[cfg(feature = "mock")] DatabaseConnection::MockDatabaseConnection(conn) => { - DatabaseTransaction::new_mock(Arc::clone(conn)).await + DatabaseTransaction::new_mock(Arc::clone(conn), None).await } DatabaseConnection::Disconnected => panic!("Disconnected"), } @@ -213,7 +213,7 @@ impl<'a> ConnectionTrait<'a> for DatabaseConnection { DatabaseConnection::SqlxSqlitePoolConnection(conn) => conn.transaction(_callback).await, #[cfg(feature = "mock")] DatabaseConnection::MockDatabaseConnection(conn) => { - let transaction = DatabaseTransaction::new_mock(Arc::clone(conn)) + let transaction = DatabaseTransaction::new_mock(Arc::clone(conn), None) .await .map_err(TransactionError::Connection)?; transaction.run(_callback).await @@ -245,6 +245,24 @@ impl DatabaseConnection { } } +impl DatabaseConnection { + /// Sets a callback to metric this connection + pub fn set_metric_callback(&mut self, callback: F) + where + F: Into, + { + match self { + #[cfg(feature = "sqlx-mysql")] + DatabaseConnection::SqlxMySqlPoolConnection(conn) => conn.set_metric_callback(callback), + #[cfg(feature = "sqlx-postgres")] + DatabaseConnection::SqlxPostgresPoolConnection(conn) => conn.set_metric_callback(callback), + #[cfg(feature = "sqlx-sqlite")] + DatabaseConnection::SqlxSqlitePoolConnection(conn) => conn.set_metric_callback(callback), + _ => {}, + } + } +} + impl DbBackend { /// Check if the URI is the same as the specified database backend. /// Returns true if they match. diff --git a/src/database/stream/query.rs b/src/database/stream/query.rs index 144a6b83..2147a8dc 100644 --- a/src/database/stream/query.rs +++ b/src/database/stream/query.rs @@ -21,36 +21,37 @@ use crate::{DbErr, InnerConnection, QueryResult, Statement}; pub struct QueryStream { stmt: Statement, conn: InnerConnection, - #[borrows(mut conn, stmt)] + metric_callback: Option, + #[borrows(mut conn, stmt, metric_callback)] #[not_covariant] stream: Pin> + 'this>>, } #[cfg(feature = "sqlx-mysql")] -impl From<(PoolConnection, Statement)> for QueryStream { - fn from((conn, stmt): (PoolConnection, Statement)) -> Self { - QueryStream::build(stmt, InnerConnection::MySql(conn)) +impl From<(PoolConnection, Statement, Option)> for QueryStream { + fn from((conn, stmt, metric_callback): (PoolConnection, Statement, Option)) -> Self { + QueryStream::build(stmt, InnerConnection::MySql(conn), metric_callback) } } #[cfg(feature = "sqlx-postgres")] -impl From<(PoolConnection, Statement)> for QueryStream { - fn from((conn, stmt): (PoolConnection, Statement)) -> Self { - QueryStream::build(stmt, InnerConnection::Postgres(conn)) +impl From<(PoolConnection, Statement, Option)> for QueryStream { + fn from((conn, stmt, metric_callback): (PoolConnection, Statement, Option)) -> Self { + QueryStream::build(stmt, InnerConnection::Postgres(conn), metric_callback) } } #[cfg(feature = "sqlx-sqlite")] -impl From<(PoolConnection, Statement)> for QueryStream { - fn from((conn, stmt): (PoolConnection, Statement)) -> Self { - QueryStream::build(stmt, InnerConnection::Sqlite(conn)) +impl From<(PoolConnection, Statement, Option)> for QueryStream { + fn from((conn, stmt, metric_callback): (PoolConnection, Statement, Option)) -> Self { + QueryStream::build(stmt, InnerConnection::Sqlite(conn), metric_callback) } } #[cfg(feature = "mock")] -impl From<(Arc, Statement)> for QueryStream { - fn from((conn, stmt): (Arc, Statement)) -> Self { - QueryStream::build(stmt, InnerConnection::Mock(conn)) +impl From<(Arc, Statement, Option)> for QueryStream { + fn from((conn, stmt, metric_callback): (Arc, Statement, Option)) -> Self { + QueryStream::build(stmt, InnerConnection::Mock(conn), metric_callback) } } @@ -61,12 +62,13 @@ impl std::fmt::Debug for QueryStream { } impl QueryStream { - #[instrument(level = "trace")] - fn build(stmt: Statement, conn: InnerConnection) -> QueryStream { + #[instrument(level = "trace", skip(metric_callback))] + fn build(stmt: Statement, conn: InnerConnection, metric_callback: Option) -> QueryStream { QueryStreamBuilder { stmt, conn, - stream_builder: |conn, stmt| { + metric_callback, + stream_builder: |conn, stmt, metric_callback| { match conn { #[cfg(feature = "sqlx-mysql")] InnerConnection::MySql(c) => { @@ -77,7 +79,7 @@ impl QueryStream { .map_ok(Into::into) .map_err(crate::sqlx_error_to_query_err), ); - if let Some(callback) = crate::metric::get_callback() { + if let Some(callback) = metric_callback.as_deref() { let info = crate::metric::Info { elapsed: _start.elapsed().unwrap_or_default(), statement: stmt, @@ -95,7 +97,7 @@ impl QueryStream { .map_ok(Into::into) .map_err(crate::sqlx_error_to_query_err), ); - if let Some(callback) = crate::metric::get_callback() { + if let Some(callback) = metric_callback.as_deref() { let info = crate::metric::Info { elapsed: _start.elapsed().unwrap_or_default(), statement: stmt, @@ -113,7 +115,7 @@ impl QueryStream { .map_ok(Into::into) .map_err(crate::sqlx_error_to_query_err), ); - if let Some(callback) = crate::metric::get_callback() { + if let Some(callback) = metric_callback.as_deref() { let info = crate::metric::Info { elapsed: _start.elapsed().unwrap_or_default(), statement: stmt, diff --git a/src/database/stream/transaction.rs b/src/database/stream/transaction.rs index d2643f63..fe1212d8 100644 --- a/src/database/stream/transaction.rs +++ b/src/database/stream/transaction.rs @@ -21,7 +21,8 @@ use crate::{DbErr, InnerConnection, QueryResult, Statement}; pub struct TransactionStream<'a> { stmt: Statement, conn: MutexGuard<'a, InnerConnection>, - #[borrows(mut conn, stmt)] + metric_callback: Option, + #[borrows(mut conn, stmt, metric_callback)] #[not_covariant] stream: Pin> + 'this>>, } @@ -33,15 +34,17 @@ impl<'a> std::fmt::Debug for TransactionStream<'a> { } impl<'a> TransactionStream<'a> { - #[instrument(level = "trace")] + #[instrument(level = "trace", skip(metric_callback))] pub(crate) async fn build( conn: MutexGuard<'a, InnerConnection>, stmt: Statement, + metric_callback: Option, ) -> TransactionStream<'a> { TransactionStreamAsyncBuilder { stmt, conn, - stream_builder: |conn, stmt| { + metric_callback, + stream_builder: |conn, stmt, metric_callback| { Box::pin(async move { match conn.deref_mut() { #[cfg(feature = "sqlx-mysql")] @@ -53,7 +56,7 @@ impl<'a> TransactionStream<'a> { .map_ok(Into::into) .map_err(crate::sqlx_error_to_query_err), ) as Pin>>>; - if let Some(callback) = crate::metric::get_callback() { + if let Some(callback) = metric_callback.as_deref() { let info = crate::metric::Info { elapsed: _start.elapsed().unwrap_or_default(), statement: stmt, @@ -71,7 +74,7 @@ impl<'a> TransactionStream<'a> { .map_ok(Into::into) .map_err(crate::sqlx_error_to_query_err), ) as Pin>>>; - if let Some(callback) = crate::metric::get_callback() { + if let Some(callback) = metric_callback.as_deref() { let info = crate::metric::Info { elapsed: _start.elapsed().unwrap_or_default(), statement: stmt, @@ -89,7 +92,7 @@ impl<'a> TransactionStream<'a> { .map_ok(Into::into) .map_err(crate::sqlx_error_to_query_err), ) as Pin>>>; - if let Some(callback) = crate::metric::get_callback() { + if let Some(callback) = metric_callback.as_deref() { let info = crate::metric::Info { elapsed: _start.elapsed().unwrap_or_default(), statement: stmt, diff --git a/src/database/transaction.rs b/src/database/transaction.rs index e26067db..e6dbf83a 100644 --- a/src/database/transaction.rs +++ b/src/database/transaction.rs @@ -17,6 +17,7 @@ pub struct DatabaseTransaction { conn: Arc>, backend: DbBackend, open: bool, + metric_callback: Option, } impl std::fmt::Debug for DatabaseTransaction { @@ -29,10 +30,12 @@ impl DatabaseTransaction { #[cfg(feature = "sqlx-mysql")] pub(crate) async fn new_mysql( inner: PoolConnection, + metric_callback: Option, ) -> Result { Self::begin( Arc::new(Mutex::new(InnerConnection::MySql(inner))), DbBackend::MySql, + metric_callback, ) .await } @@ -40,10 +43,12 @@ impl DatabaseTransaction { #[cfg(feature = "sqlx-postgres")] pub(crate) async fn new_postgres( inner: PoolConnection, + metric_callback: Option, ) -> Result { Self::begin( Arc::new(Mutex::new(InnerConnection::Postgres(inner))), DbBackend::Postgres, + metric_callback, ) .await } @@ -51,10 +56,12 @@ impl DatabaseTransaction { #[cfg(feature = "sqlx-sqlite")] pub(crate) async fn new_sqlite( inner: PoolConnection, + metric_callback: Option, ) -> Result { Self::begin( Arc::new(Mutex::new(InnerConnection::Sqlite(inner))), DbBackend::Sqlite, + metric_callback, ) .await } @@ -62,20 +69,27 @@ impl DatabaseTransaction { #[cfg(feature = "mock")] pub(crate) async fn new_mock( inner: Arc, + metric_callback: Option, ) -> Result { let backend = inner.get_database_backend(); - Self::begin(Arc::new(Mutex::new(InnerConnection::Mock(inner))), backend).await + Self::begin( + Arc::new(Mutex::new(InnerConnection::Mock(inner))), + backend, + metric_callback, + ).await } - #[instrument(level = "trace")] + #[instrument(level = "trace", skip(metric_callback))] async fn begin( conn: Arc>, backend: DbBackend, + metric_callback: Option, ) -> Result { let res = DatabaseTransaction { conn, backend, open: true, + metric_callback, }; match *res.conn.lock().await { #[cfg(feature = "sqlx-mysql")] @@ -245,7 +259,7 @@ impl<'a> ConnectionTrait<'a> for DatabaseTransaction { let query = crate::driver::sqlx_mysql::sqlx_query(&stmt); let _start = std::time::SystemTime::now(); let res = query.execute(conn).await.map(Into::into); - if let Some(callback) = crate::metric::get_callback() { + if let Some(callback) = self.metric_callback.as_deref() { let info = crate::metric::Info { elapsed: _start.elapsed().unwrap_or_default(), statement: &stmt, @@ -259,7 +273,7 @@ impl<'a> ConnectionTrait<'a> for DatabaseTransaction { let query = crate::driver::sqlx_postgres::sqlx_query(&stmt); let _start = std::time::SystemTime::now(); let res = query.execute(conn).await.map(Into::into); - if let Some(callback) = crate::metric::get_callback() { + if let Some(callback) = self.metric_callback.as_deref() { let info = crate::metric::Info { elapsed: _start.elapsed().unwrap_or_default(), statement: &stmt, @@ -273,7 +287,7 @@ impl<'a> ConnectionTrait<'a> for DatabaseTransaction { let query = crate::driver::sqlx_sqlite::sqlx_query(&stmt); let _start = std::time::SystemTime::now(); let res = query.execute(conn).await.map(Into::into); - if let Some(callback) = crate::metric::get_callback() { + if let Some(callback) = self.metric_callback.as_deref() { let info = crate::metric::Info { elapsed: _start.elapsed().unwrap_or_default(), statement: &stmt, @@ -362,13 +376,17 @@ impl<'a> ConnectionTrait<'a> for DatabaseTransaction { stmt: Statement, ) -> Pin> + 'a>> { Box::pin( - async move { Ok(crate::TransactionStream::build(self.conn.lock().await, stmt).await) }, + async move { Ok(crate::TransactionStream::build(self.conn.lock().await, stmt, self.metric_callback.clone()).await) }, ) } #[instrument(level = "trace")] async fn begin(&self) -> Result { - DatabaseTransaction::begin(Arc::clone(&self.conn), self.backend).await + DatabaseTransaction::begin( + Arc::clone(&self.conn), + self.backend, + self.metric_callback.clone() + ).await } /// Execute the function inside a transaction. diff --git a/src/driver/sqlx_mysql.rs b/src/driver/sqlx_mysql.rs index 2b2efd68..7216c226 100644 --- a/src/driver/sqlx_mysql.rs +++ b/src/driver/sqlx_mysql.rs @@ -21,9 +21,16 @@ use super::sqlx_common::*; pub struct SqlxMySqlConnector; /// Defines a sqlx MySQL pool -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct SqlxMySqlPoolConnection { pool: MySqlPool, + metric_callback: Option, +} + +impl std::fmt::Debug for SqlxMySqlPoolConnection { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "SqlxMySqlPoolConnection {{ pool: {:?} }}", self.pool) + } } impl SqlxMySqlConnector { @@ -45,7 +52,7 @@ impl SqlxMySqlConnector { } match options.pool_options().connect_with(opt).await { Ok(pool) => Ok(DatabaseConnection::SqlxMySqlPoolConnection( - SqlxMySqlPoolConnection { pool }, + SqlxMySqlPoolConnection { pool, metric_callback: None }, )), Err(e) => Err(sqlx_error_to_conn_err(e)), } @@ -55,7 +62,7 @@ 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 }) + DatabaseConnection::SqlxMySqlPoolConnection(SqlxMySqlPoolConnection { pool, metric_callback: None }) } } @@ -72,7 +79,7 @@ impl SqlxMySqlPoolConnection { Ok(res) => Ok(res.into()), Err(err) => Err(sqlx_error_to_exec_err(err)), }; - if let Some(callback) = crate::metric::get_callback() { + if let Some(callback) = self.metric_callback.as_deref() { let info = crate::metric::Info { elapsed: _start.elapsed().unwrap_or_default(), statement: &stmt, @@ -102,7 +109,7 @@ impl SqlxMySqlPoolConnection { _ => Err(DbErr::Query(err.to_string())), }, }; - if let Some(callback) = crate::metric::get_callback() { + if let Some(callback) = self.metric_callback.as_deref() { let info = crate::metric::Info { elapsed: _start.elapsed().unwrap_or_default(), statement: &stmt, @@ -129,7 +136,7 @@ impl SqlxMySqlPoolConnection { Ok(rows) => Ok(rows.into_iter().map(|r| r.into()).collect()), Err(err) => Err(sqlx_error_to_query_err(err)), }; - if let Some(callback) = crate::metric::get_callback() { + if let Some(callback) = self.metric_callback.as_deref() { let info = crate::metric::Info { elapsed: _start.elapsed().unwrap_or_default(), statement: &stmt, @@ -150,7 +157,7 @@ impl SqlxMySqlPoolConnection { debug_print!("{}", stmt); if let Ok(conn) = self.pool.acquire().await { - Ok(QueryStream::from((conn, stmt))) + Ok(QueryStream::from((conn, stmt, self.metric_callback.clone()))) } else { Err(DbErr::Query( "Failed to acquire connection from pool.".to_owned(), @@ -162,7 +169,7 @@ impl SqlxMySqlPoolConnection { #[instrument(level = "trace")] pub async fn begin(&self) -> Result { if let Ok(conn) = self.pool.acquire().await { - DatabaseTransaction::new_mysql(conn).await + DatabaseTransaction::new_mysql(conn, self.metric_callback.clone()).await } else { Err(DbErr::Query( "Failed to acquire connection from pool.".to_owned(), @@ -182,7 +189,7 @@ impl SqlxMySqlPoolConnection { E: std::error::Error + Send, { if let Ok(conn) = self.pool.acquire().await { - let transaction = DatabaseTransaction::new_mysql(conn) + let transaction = DatabaseTransaction::new_mysql(conn, self.metric_callback.clone()) .await .map_err(|e| TransactionError::Connection(e))?; transaction.run(callback).await @@ -192,6 +199,13 @@ impl SqlxMySqlPoolConnection { ))) } } + + pub(crate) fn set_metric_callback(&mut self, callback: F) + where + F: Into, + { + self.metric_callback = Some(callback.into()); + } } impl From for QueryResult { diff --git a/src/driver/sqlx_postgres.rs b/src/driver/sqlx_postgres.rs index 121e4e72..5f90e515 100644 --- a/src/driver/sqlx_postgres.rs +++ b/src/driver/sqlx_postgres.rs @@ -21,9 +21,16 @@ use super::sqlx_common::*; pub struct SqlxPostgresConnector; /// Defines a sqlx PostgreSQL pool -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct SqlxPostgresPoolConnection { pool: PgPool, + metric_callback: Option, +} + +impl std::fmt::Debug for SqlxPostgresPoolConnection { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "SqlxPostgresPoolConnection {{ pool: {:?} }}", self.pool) + } } impl SqlxPostgresConnector { @@ -45,7 +52,7 @@ impl SqlxPostgresConnector { } match options.pool_options().connect_with(opt).await { Ok(pool) => Ok(DatabaseConnection::SqlxPostgresPoolConnection( - SqlxPostgresPoolConnection { pool }, + SqlxPostgresPoolConnection { pool, metric_callback: None }, )), Err(e) => Err(sqlx_error_to_conn_err(e)), } @@ -55,7 +62,7 @@ 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 }) + DatabaseConnection::SqlxPostgresPoolConnection(SqlxPostgresPoolConnection { pool, metric_callback: None }) } } @@ -72,7 +79,7 @@ impl SqlxPostgresPoolConnection { Ok(res) => Ok(res.into()), Err(err) => Err(sqlx_error_to_exec_err(err)), }; - if let Some(callback) = crate::metric::get_callback() { + if let Some(callback) = self.metric_callback.as_deref() { let info = crate::metric::Info { elapsed: _start.elapsed().unwrap_or_default(), statement: &stmt, @@ -102,7 +109,7 @@ impl SqlxPostgresPoolConnection { _ => Err(DbErr::Query(err.to_string())), }, }; - if let Some(callback) = crate::metric::get_callback() { + if let Some(callback) = self.metric_callback.as_deref() { let info = crate::metric::Info { elapsed: _start.elapsed().unwrap_or_default(), statement: &stmt, @@ -129,7 +136,7 @@ impl SqlxPostgresPoolConnection { Ok(rows) => Ok(rows.into_iter().map(|r| r.into()).collect()), Err(err) => Err(sqlx_error_to_query_err(err)), }; - if let Some(callback) = crate::metric::get_callback() { + if let Some(callback) = self.metric_callback.as_deref() { let info = crate::metric::Info { elapsed: _start.elapsed().unwrap_or_default(), statement: &stmt, @@ -150,7 +157,7 @@ impl SqlxPostgresPoolConnection { debug_print!("{}", stmt); if let Ok(conn) = self.pool.acquire().await { - Ok(QueryStream::from((conn, stmt))) + Ok(QueryStream::from((conn, stmt, self.metric_callback.clone()))) } else { Err(DbErr::Query( "Failed to acquire connection from pool.".to_owned(), @@ -162,7 +169,7 @@ impl SqlxPostgresPoolConnection { #[instrument(level = "trace")] pub async fn begin(&self) -> Result { if let Ok(conn) = self.pool.acquire().await { - DatabaseTransaction::new_postgres(conn).await + DatabaseTransaction::new_postgres(conn, self.metric_callback.clone()).await } else { Err(DbErr::Query( "Failed to acquire connection from pool.".to_owned(), @@ -182,7 +189,7 @@ impl SqlxPostgresPoolConnection { E: std::error::Error + Send, { if let Ok(conn) = self.pool.acquire().await { - let transaction = DatabaseTransaction::new_postgres(conn) + let transaction = DatabaseTransaction::new_postgres(conn, self.metric_callback.clone()) .await .map_err(|e| TransactionError::Connection(e))?; transaction.run(callback).await @@ -192,6 +199,13 @@ impl SqlxPostgresPoolConnection { ))) } } + + pub(crate) fn set_metric_callback(&mut self, callback: F) + where + F: Into, + { + self.metric_callback = Some(callback.into()); + } } impl From for QueryResult { diff --git a/src/driver/sqlx_sqlite.rs b/src/driver/sqlx_sqlite.rs index 9cfd9a72..20f4954e 100644 --- a/src/driver/sqlx_sqlite.rs +++ b/src/driver/sqlx_sqlite.rs @@ -21,9 +21,16 @@ use super::sqlx_common::*; pub struct SqlxSqliteConnector; /// Defines a sqlx SQLite pool -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct SqlxSqlitePoolConnection { pool: SqlitePool, + metric_callback: Option, +} + +impl std::fmt::Debug for SqlxSqlitePoolConnection { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "SqlxSqlitePoolConnection {{ pool: {:?} }}", self.pool) + } } impl SqlxSqliteConnector { @@ -49,7 +56,7 @@ impl SqlxSqliteConnector { } match options.pool_options().connect_with(opt).await { Ok(pool) => Ok(DatabaseConnection::SqlxSqlitePoolConnection( - SqlxSqlitePoolConnection { pool }, + SqlxSqlitePoolConnection { pool, metric_callback: None }, )), Err(e) => Err(sqlx_error_to_conn_err(e)), } @@ -59,7 +66,7 @@ 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 }) + DatabaseConnection::SqlxSqlitePoolConnection(SqlxSqlitePoolConnection { pool, metric_callback: None }) } } @@ -76,7 +83,7 @@ impl SqlxSqlitePoolConnection { Ok(res) => Ok(res.into()), Err(err) => Err(sqlx_error_to_exec_err(err)), }; - if let Some(callback) = crate::metric::get_callback() { + if let Some(callback) = self.metric_callback.as_deref() { let info = crate::metric::Info { elapsed: _start.elapsed().unwrap_or_default(), statement: &stmt, @@ -106,7 +113,7 @@ impl SqlxSqlitePoolConnection { _ => Err(DbErr::Query(err.to_string())), }, }; - if let Some(callback) = crate::metric::get_callback() { + if let Some(callback) = self.metric_callback.as_deref() { let info = crate::metric::Info { elapsed: _start.elapsed().unwrap_or_default(), statement: &stmt, @@ -133,7 +140,7 @@ impl SqlxSqlitePoolConnection { Ok(rows) => Ok(rows.into_iter().map(|r| r.into()).collect()), Err(err) => Err(sqlx_error_to_query_err(err)), }; - if let Some(callback) = crate::metric::get_callback() { + if let Some(callback) = self.metric_callback.as_deref() { let info = crate::metric::Info { elapsed: _start.elapsed().unwrap_or_default(), statement: &stmt, @@ -154,7 +161,7 @@ impl SqlxSqlitePoolConnection { debug_print!("{}", stmt); if let Ok(conn) = self.pool.acquire().await { - Ok(QueryStream::from((conn, stmt))) + Ok(QueryStream::from((conn, stmt, self.metric_callback.clone()))) } else { Err(DbErr::Query( "Failed to acquire connection from pool.".to_owned(), @@ -166,7 +173,7 @@ impl SqlxSqlitePoolConnection { #[instrument(level = "trace")] pub async fn begin(&self) -> Result { if let Ok(conn) = self.pool.acquire().await { - DatabaseTransaction::new_sqlite(conn).await + DatabaseTransaction::new_sqlite(conn, self.metric_callback.clone()).await } else { Err(DbErr::Query( "Failed to acquire connection from pool.".to_owned(), @@ -186,7 +193,7 @@ impl SqlxSqlitePoolConnection { E: std::error::Error + Send, { if let Ok(conn) = self.pool.acquire().await { - let transaction = DatabaseTransaction::new_sqlite(conn) + let transaction = DatabaseTransaction::new_sqlite(conn, self.metric_callback.clone()) .await .map_err(|e| TransactionError::Connection(e))?; transaction.run(callback).await @@ -196,6 +203,13 @@ impl SqlxSqlitePoolConnection { ))) } } + + pub(crate) fn set_metric_callback(&mut self, callback: F) + where + F: Into, + { + self.metric_callback = Some(callback.into()); + } } impl From for QueryResult { diff --git a/src/metric.rs b/src/metric.rs index 4eab0e74..4ea62ef2 100644 --- a/src/metric.rs +++ b/src/metric.rs @@ -1,10 +1,6 @@ -use std::time::Duration; +use std::{time::Duration, sync::Arc}; -use once_cell::sync::OnceCell; - -type Callback = Box) + Send + Sync>; - -static METRIC: OnceCell = OnceCell::new(); +pub(crate) type Callback = Arc) + Send + Sync>; #[derive(Debug)] /// Query execution infos @@ -14,15 +10,3 @@ pub struct Info<'a> { /// Query data pub statement: &'a crate::Statement, } - -/// Sets a new metric callback, returning it if already set -pub fn set_callback(callback: F) -> Result<(), Callback> -where - F: Fn(&Info<'_>) + Send + Sync + 'static, -{ - METRIC.set(Box::new(callback)) -} - -pub(crate) fn get_callback() -> Option<&'static Callback> { - METRIC.get() -} From aaf11dd2654e00a915a79488d2c4e4fd118ad601 Mon Sep 17 00:00:00 2001 From: Marco Napetti Date: Thu, 9 Dec 2021 19:17:41 +0100 Subject: [PATCH 09/36] Into doesn't works --- src/database/db_connection.rs | 2 +- src/driver/sqlx_mysql.rs | 6 +++--- src/driver/sqlx_postgres.rs | 6 +++--- src/driver/sqlx_sqlite.rs | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/database/db_connection.rs b/src/database/db_connection.rs index 3a090b6f..24b30e9c 100644 --- a/src/database/db_connection.rs +++ b/src/database/db_connection.rs @@ -249,7 +249,7 @@ impl DatabaseConnection { /// Sets a callback to metric this connection pub fn set_metric_callback(&mut self, callback: F) where - F: Into, + F: Fn(&crate::metric::Info<'_>) + Send + Sync + 'static, { match self { #[cfg(feature = "sqlx-mysql")] diff --git a/src/driver/sqlx_mysql.rs b/src/driver/sqlx_mysql.rs index 7216c226..338b09d1 100644 --- a/src/driver/sqlx_mysql.rs +++ b/src/driver/sqlx_mysql.rs @@ -1,4 +1,4 @@ -use std::{future::Future, pin::Pin}; +use std::{future::Future, pin::Pin, sync::Arc}; use sqlx::{ mysql::{MySqlArguments, MySqlConnectOptions, MySqlQueryResult, MySqlRow}, @@ -202,9 +202,9 @@ impl SqlxMySqlPoolConnection { pub(crate) fn set_metric_callback(&mut self, callback: F) where - F: Into, + F: Fn(&crate::metric::Info<'_>) + Send + Sync + 'static, { - self.metric_callback = Some(callback.into()); + self.metric_callback = Some(Arc::new(callback)); } } diff --git a/src/driver/sqlx_postgres.rs b/src/driver/sqlx_postgres.rs index 5f90e515..7eebe94f 100644 --- a/src/driver/sqlx_postgres.rs +++ b/src/driver/sqlx_postgres.rs @@ -1,4 +1,4 @@ -use std::{future::Future, pin::Pin}; +use std::{future::Future, pin::Pin, sync::Arc}; use sqlx::{ postgres::{PgArguments, PgConnectOptions, PgQueryResult, PgRow}, @@ -202,9 +202,9 @@ impl SqlxPostgresPoolConnection { pub(crate) fn set_metric_callback(&mut self, callback: F) where - F: Into, + F: Fn(&crate::metric::Info<'_>) + Send + Sync + 'static, { - self.metric_callback = Some(callback.into()); + self.metric_callback = Some(Arc::new(callback)); } } diff --git a/src/driver/sqlx_sqlite.rs b/src/driver/sqlx_sqlite.rs index 20f4954e..c2afbbf4 100644 --- a/src/driver/sqlx_sqlite.rs +++ b/src/driver/sqlx_sqlite.rs @@ -1,4 +1,4 @@ -use std::{future::Future, pin::Pin}; +use std::{future::Future, pin::Pin, sync::Arc}; use sqlx::{ sqlite::{SqliteArguments, SqliteConnectOptions, SqliteQueryResult, SqliteRow}, @@ -206,9 +206,9 @@ impl SqlxSqlitePoolConnection { pub(crate) fn set_metric_callback(&mut self, callback: F) where - F: Into, + F: Fn(&crate::metric::Info<'_>) + Send + Sync + 'static, { - self.metric_callback = Some(callback.into()); + self.metric_callback = Some(Arc::new(callback)); } } From 9a342546f3a329e0561cf6566e699875fbe02eea Mon Sep 17 00:00:00 2001 From: Marco Napetti Date: Fri, 10 Dec 2021 10:09:09 +0100 Subject: [PATCH 10/36] use macro to simplify code, add failure boolean --- src/database/stream/query.rs | 63 ++++++++++-------------------- src/database/stream/transaction.rs | 63 ++++++++++-------------------- src/database/transaction.rs | 39 +++++------------- src/driver/sqlx_mysql.rs | 63 ++++++++++-------------------- src/driver/sqlx_postgres.rs | 63 ++++++++++-------------------- src/driver/sqlx_sqlite.rs | 63 ++++++++++-------------------- src/metric.rs | 43 ++++++++++++++++++++ 7 files changed, 157 insertions(+), 240 deletions(-) diff --git a/src/database/stream/query.rs b/src/database/stream/query.rs index 2147a8dc..f967268b 100644 --- a/src/database/stream/query.rs +++ b/src/database/stream/query.rs @@ -73,56 +73,35 @@ impl QueryStream { #[cfg(feature = "sqlx-mysql")] InnerConnection::MySql(c) => { let query = crate::driver::sqlx_mysql::sqlx_query(stmt); - let _start = std::time::SystemTime::now(); - let res = Box::pin( - c.fetch(query) - .map_ok(Into::into) - .map_err(crate::sqlx_error_to_query_err), - ); - if let Some(callback) = metric_callback.as_deref() { - let info = crate::metric::Info { - elapsed: _start.elapsed().unwrap_or_default(), - statement: stmt, - }; - callback(&info); - } - res + crate::metric::metric_ok!(metric_callback, stmt, { + Box::pin( + c.fetch(query) + .map_ok(Into::into) + .map_err(crate::sqlx_error_to_query_err), + ) + }) } #[cfg(feature = "sqlx-postgres")] InnerConnection::Postgres(c) => { let query = crate::driver::sqlx_postgres::sqlx_query(stmt); - let _start = std::time::SystemTime::now(); - let res = Box::pin( - c.fetch(query) - .map_ok(Into::into) - .map_err(crate::sqlx_error_to_query_err), - ); - if let Some(callback) = metric_callback.as_deref() { - let info = crate::metric::Info { - elapsed: _start.elapsed().unwrap_or_default(), - statement: stmt, - }; - callback(&info); - } - res + crate::metric::metric_ok!(metric_callback, stmt, { + Box::pin( + c.fetch(query) + .map_ok(Into::into) + .map_err(crate::sqlx_error_to_query_err), + ) + }) } #[cfg(feature = "sqlx-sqlite")] InnerConnection::Sqlite(c) => { let query = crate::driver::sqlx_sqlite::sqlx_query(stmt); - let _start = std::time::SystemTime::now(); - let res = Box::pin( - c.fetch(query) - .map_ok(Into::into) - .map_err(crate::sqlx_error_to_query_err), - ); - if let Some(callback) = metric_callback.as_deref() { - let info = crate::metric::Info { - elapsed: _start.elapsed().unwrap_or_default(), - statement: stmt, - }; - callback(&info); - } - res + crate::metric::metric_ok!(metric_callback, stmt, { + Box::pin( + c.fetch(query) + .map_ok(Into::into) + .map_err(crate::sqlx_error_to_query_err), + ) + }) } #[cfg(feature = "mock")] InnerConnection::Mock(c) => c.fetch(stmt), diff --git a/src/database/stream/transaction.rs b/src/database/stream/transaction.rs index fe1212d8..1995e0b4 100644 --- a/src/database/stream/transaction.rs +++ b/src/database/stream/transaction.rs @@ -50,56 +50,35 @@ impl<'a> TransactionStream<'a> { #[cfg(feature = "sqlx-mysql")] InnerConnection::MySql(c) => { let query = crate::driver::sqlx_mysql::sqlx_query(stmt); - let _start = std::time::SystemTime::now(); - let res = Box::pin( - c.fetch(query) - .map_ok(Into::into) - .map_err(crate::sqlx_error_to_query_err), - ) as Pin>>>; - if let Some(callback) = metric_callback.as_deref() { - let info = crate::metric::Info { - elapsed: _start.elapsed().unwrap_or_default(), - statement: stmt, - }; - callback(&info); - } - res + crate::metric::metric_ok!(metric_callback, stmt, { + Box::pin( + c.fetch(query) + .map_ok(Into::into) + .map_err(crate::sqlx_error_to_query_err), + ) as Pin>>> + }) } #[cfg(feature = "sqlx-postgres")] InnerConnection::Postgres(c) => { let query = crate::driver::sqlx_postgres::sqlx_query(stmt); - let _start = std::time::SystemTime::now(); - let res = Box::pin( - c.fetch(query) - .map_ok(Into::into) - .map_err(crate::sqlx_error_to_query_err), - ) as Pin>>>; - if let Some(callback) = metric_callback.as_deref() { - let info = crate::metric::Info { - elapsed: _start.elapsed().unwrap_or_default(), - statement: stmt, - }; - callback(&info); - } - res + crate::metric::metric_ok!(metric_callback, stmt, { + Box::pin( + c.fetch(query) + .map_ok(Into::into) + .map_err(crate::sqlx_error_to_query_err), + ) as Pin>>> + }) } #[cfg(feature = "sqlx-sqlite")] InnerConnection::Sqlite(c) => { let query = crate::driver::sqlx_sqlite::sqlx_query(stmt); - let _start = std::time::SystemTime::now(); - let res = Box::pin( - c.fetch(query) - .map_ok(Into::into) - .map_err(crate::sqlx_error_to_query_err), - ) as Pin>>>; - if let Some(callback) = metric_callback.as_deref() { - let info = crate::metric::Info { - elapsed: _start.elapsed().unwrap_or_default(), - statement: stmt, - }; - callback(&info); - } - res + crate::metric::metric_ok!(metric_callback, stmt, { + Box::pin( + c.fetch(query) + .map_ok(Into::into) + .map_err(crate::sqlx_error_to_query_err), + ) as Pin>>> + }) } #[cfg(feature = "mock")] InnerConnection::Mock(c) => c.fetch(stmt), diff --git a/src/database/transaction.rs b/src/database/transaction.rs index e6dbf83a..790483b4 100644 --- a/src/database/transaction.rs +++ b/src/database/transaction.rs @@ -257,44 +257,23 @@ impl<'a> ConnectionTrait<'a> for DatabaseTransaction { #[cfg(feature = "sqlx-mysql")] InnerConnection::MySql(conn) => { let query = crate::driver::sqlx_mysql::sqlx_query(&stmt); - let _start = std::time::SystemTime::now(); - let res = query.execute(conn).await.map(Into::into); - if let Some(callback) = self.metric_callback.as_deref() { - let info = crate::metric::Info { - elapsed: _start.elapsed().unwrap_or_default(), - statement: &stmt, - }; - callback(&info); - } - res + crate::metric::metric!(self.metric_callback, &stmt, { + query.execute(conn).await.map(Into::into) + }) } #[cfg(feature = "sqlx-postgres")] InnerConnection::Postgres(conn) => { let query = crate::driver::sqlx_postgres::sqlx_query(&stmt); - let _start = std::time::SystemTime::now(); - let res = query.execute(conn).await.map(Into::into); - if let Some(callback) = self.metric_callback.as_deref() { - let info = crate::metric::Info { - elapsed: _start.elapsed().unwrap_or_default(), - statement: &stmt, - }; - callback(&info); - } - res + crate::metric::metric!(self.metric_callback, &stmt, { + query.execute(conn).await.map(Into::into) + }) } #[cfg(feature = "sqlx-sqlite")] InnerConnection::Sqlite(conn) => { let query = crate::driver::sqlx_sqlite::sqlx_query(&stmt); - let _start = std::time::SystemTime::now(); - let res = query.execute(conn).await.map(Into::into); - if let Some(callback) = self.metric_callback.as_deref() { - let info = crate::metric::Info { - elapsed: _start.elapsed().unwrap_or_default(), - statement: &stmt, - }; - callback(&info); - } - res + crate::metric::metric!(self.metric_callback, &stmt, { + query.execute(conn).await.map(Into::into) + }) } #[cfg(feature = "mock")] InnerConnection::Mock(conn) => return conn.execute(stmt), diff --git a/src/driver/sqlx_mysql.rs b/src/driver/sqlx_mysql.rs index 338b09d1..e818a6c4 100644 --- a/src/driver/sqlx_mysql.rs +++ b/src/driver/sqlx_mysql.rs @@ -74,19 +74,12 @@ impl SqlxMySqlPoolConnection { let query = sqlx_query(&stmt); if let Ok(conn) = &mut self.pool.acquire().await { - let _start = std::time::SystemTime::now(); - let res = match query.execute(conn).await { - Ok(res) => Ok(res.into()), - Err(err) => Err(sqlx_error_to_exec_err(err)), - }; - if let Some(callback) = self.metric_callback.as_deref() { - let info = crate::metric::Info { - elapsed: _start.elapsed().unwrap_or_default(), - statement: &stmt, - }; - callback(&info); - } - res + crate::metric::metric!(self.metric_callback, &stmt, { + match query.execute(conn).await { + Ok(res) => Ok(res.into()), + Err(err) => Err(sqlx_error_to_exec_err(err)), + } + }) } else { Err(DbErr::Exec( "Failed to acquire connection from pool.".to_owned(), @@ -101,22 +94,15 @@ impl SqlxMySqlPoolConnection { let query = sqlx_query(&stmt); if let Ok(conn) = &mut self.pool.acquire().await { - let _start = std::time::SystemTime::now(); - let res = match query.fetch_one(conn).await { - Ok(row) => Ok(Some(row.into())), - Err(err) => match err { - sqlx::Error::RowNotFound => Ok(None), - _ => Err(DbErr::Query(err.to_string())), - }, - }; - if let Some(callback) = self.metric_callback.as_deref() { - let info = crate::metric::Info { - elapsed: _start.elapsed().unwrap_or_default(), - statement: &stmt, - }; - callback(&info); - } - res + crate::metric::metric!(self.metric_callback, &stmt, { + match query.fetch_one(conn).await { + Ok(row) => Ok(Some(row.into())), + Err(err) => match err { + sqlx::Error::RowNotFound => Ok(None), + _ => Err(DbErr::Query(err.to_string())), + }, + } + }) } else { Err(DbErr::Query( "Failed to acquire connection from pool.".to_owned(), @@ -131,19 +117,12 @@ impl SqlxMySqlPoolConnection { let query = sqlx_query(&stmt); if let Ok(conn) = &mut self.pool.acquire().await { - let _start = std::time::SystemTime::now(); - let res = match query.fetch_all(conn).await { - Ok(rows) => Ok(rows.into_iter().map(|r| r.into()).collect()), - Err(err) => Err(sqlx_error_to_query_err(err)), - }; - if let Some(callback) = self.metric_callback.as_deref() { - let info = crate::metric::Info { - elapsed: _start.elapsed().unwrap_or_default(), - statement: &stmt, - }; - callback(&info); - } - res + crate::metric::metric!(self.metric_callback, &stmt, { + match query.fetch_all(conn).await { + Ok(rows) => Ok(rows.into_iter().map(|r| r.into()).collect()), + Err(err) => Err(sqlx_error_to_query_err(err)), + } + }) } else { Err(DbErr::Query( "Failed to acquire connection from pool.".to_owned(), diff --git a/src/driver/sqlx_postgres.rs b/src/driver/sqlx_postgres.rs index 7eebe94f..bf72f0de 100644 --- a/src/driver/sqlx_postgres.rs +++ b/src/driver/sqlx_postgres.rs @@ -74,19 +74,12 @@ impl SqlxPostgresPoolConnection { let query = sqlx_query(&stmt); if let Ok(conn) = &mut self.pool.acquire().await { - let _start = std::time::SystemTime::now(); - let res = match query.execute(conn).await { - Ok(res) => Ok(res.into()), - Err(err) => Err(sqlx_error_to_exec_err(err)), - }; - if let Some(callback) = self.metric_callback.as_deref() { - let info = crate::metric::Info { - elapsed: _start.elapsed().unwrap_or_default(), - statement: &stmt, - }; - callback(&info); - } - res + crate::metric::metric!(self.metric_callback, &stmt, { + match query.execute(conn).await { + Ok(res) => Ok(res.into()), + Err(err) => Err(sqlx_error_to_exec_err(err)), + } + }) } else { Err(DbErr::Exec( "Failed to acquire connection from pool.".to_owned(), @@ -101,22 +94,15 @@ impl SqlxPostgresPoolConnection { let query = sqlx_query(&stmt); if let Ok(conn) = &mut self.pool.acquire().await { - let _start = std::time::SystemTime::now(); - let res = match query.fetch_one(conn).await { - Ok(row) => Ok(Some(row.into())), - Err(err) => match err { - sqlx::Error::RowNotFound => Ok(None), - _ => Err(DbErr::Query(err.to_string())), - }, - }; - if let Some(callback) = self.metric_callback.as_deref() { - let info = crate::metric::Info { - elapsed: _start.elapsed().unwrap_or_default(), - statement: &stmt, - }; - callback(&info); - } - res + crate::metric::metric!(self.metric_callback, &stmt, { + match query.fetch_one(conn).await { + Ok(row) => Ok(Some(row.into())), + Err(err) => match err { + sqlx::Error::RowNotFound => Ok(None), + _ => Err(DbErr::Query(err.to_string())), + }, + } + }) } else { Err(DbErr::Query( "Failed to acquire connection from pool.".to_owned(), @@ -131,19 +117,12 @@ impl SqlxPostgresPoolConnection { let query = sqlx_query(&stmt); if let Ok(conn) = &mut self.pool.acquire().await { - let _start = std::time::SystemTime::now(); - let res = match query.fetch_all(conn).await { - Ok(rows) => Ok(rows.into_iter().map(|r| r.into()).collect()), - Err(err) => Err(sqlx_error_to_query_err(err)), - }; - if let Some(callback) = self.metric_callback.as_deref() { - let info = crate::metric::Info { - elapsed: _start.elapsed().unwrap_or_default(), - statement: &stmt, - }; - callback(&info); - } - res + crate::metric::metric!(self.metric_callback, &stmt, { + match query.fetch_all(conn).await { + Ok(rows) => Ok(rows.into_iter().map(|r| r.into()).collect()), + Err(err) => Err(sqlx_error_to_query_err(err)), + } + }) } else { Err(DbErr::Query( "Failed to acquire connection from pool.".to_owned(), diff --git a/src/driver/sqlx_sqlite.rs b/src/driver/sqlx_sqlite.rs index c2afbbf4..d3498dc1 100644 --- a/src/driver/sqlx_sqlite.rs +++ b/src/driver/sqlx_sqlite.rs @@ -78,19 +78,12 @@ impl SqlxSqlitePoolConnection { let query = sqlx_query(&stmt); if let Ok(conn) = &mut self.pool.acquire().await { - let _start = std::time::SystemTime::now(); - let res = match query.execute(conn).await { - Ok(res) => Ok(res.into()), - Err(err) => Err(sqlx_error_to_exec_err(err)), - }; - if let Some(callback) = self.metric_callback.as_deref() { - let info = crate::metric::Info { - elapsed: _start.elapsed().unwrap_or_default(), - statement: &stmt, - }; - callback(&info); - } - res + crate::metric::metric!(self.metric_callback, &stmt, { + match query.execute(conn).await { + Ok(res) => Ok(res.into()), + Err(err) => Err(sqlx_error_to_exec_err(err)), + } + }) } else { Err(DbErr::Exec( "Failed to acquire connection from pool.".to_owned(), @@ -105,22 +98,15 @@ impl SqlxSqlitePoolConnection { let query = sqlx_query(&stmt); if let Ok(conn) = &mut self.pool.acquire().await { - let _start = std::time::SystemTime::now(); - let res = match query.fetch_one(conn).await { - Ok(row) => Ok(Some(row.into())), - Err(err) => match err { - sqlx::Error::RowNotFound => Ok(None), - _ => Err(DbErr::Query(err.to_string())), - }, - }; - if let Some(callback) = self.metric_callback.as_deref() { - let info = crate::metric::Info { - elapsed: _start.elapsed().unwrap_or_default(), - statement: &stmt, - }; - callback(&info); - } - res + crate::metric::metric!(self.metric_callback, &stmt, { + match query.fetch_one(conn).await { + Ok(row) => Ok(Some(row.into())), + Err(err) => match err { + sqlx::Error::RowNotFound => Ok(None), + _ => Err(DbErr::Query(err.to_string())), + }, + } + }) } else { Err(DbErr::Query( "Failed to acquire connection from pool.".to_owned(), @@ -135,19 +121,12 @@ impl SqlxSqlitePoolConnection { let query = sqlx_query(&stmt); if let Ok(conn) = &mut self.pool.acquire().await { - let _start = std::time::SystemTime::now(); - let res = match query.fetch_all(conn).await { - Ok(rows) => Ok(rows.into_iter().map(|r| r.into()).collect()), - Err(err) => Err(sqlx_error_to_query_err(err)), - }; - if let Some(callback) = self.metric_callback.as_deref() { - let info = crate::metric::Info { - elapsed: _start.elapsed().unwrap_or_default(), - statement: &stmt, - }; - callback(&info); - } - res + crate::metric::metric!(self.metric_callback, &stmt, { + match query.fetch_all(conn).await { + Ok(rows) => Ok(rows.into_iter().map(|r| r.into()).collect()), + Err(err) => Err(sqlx_error_to_query_err(err)), + } + }) } else { Err(DbErr::Query( "Failed to acquire connection from pool.".to_owned(), diff --git a/src/metric.rs b/src/metric.rs index 4ea62ef2..7aa3a0a2 100644 --- a/src/metric.rs +++ b/src/metric.rs @@ -2,6 +2,8 @@ use std::{time::Duration, sync::Arc}; pub(crate) type Callback = Arc) + Send + Sync>; +pub(crate) use inner::{metric, metric_ok}; + #[derive(Debug)] /// Query execution infos pub struct Info<'a> { @@ -9,4 +11,45 @@ pub struct Info<'a> { pub elapsed: Duration, /// Query data pub statement: &'a crate::Statement, + /// Query execution failed + pub failed: bool, +} + +mod inner { + macro_rules! metric { + ($metric_callback:expr, $stmt:expr, $code:block) => { + { + let _start = std::time::SystemTime::now(); + let res = $code; + if let Some(callback) = $metric_callback.as_deref() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: $stmt, + failed: res.is_err(), + }; + callback(&info); + } + res + } + }; + } + pub(crate) use metric; + macro_rules! metric_ok { + ($metric_callback:expr, $stmt:expr, $code:block) => { + { + let _start = std::time::SystemTime::now(); + let res = $code; + if let Some(callback) = $metric_callback.as_deref() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: $stmt, + failed: false, + }; + callback(&info); + } + res + } + }; + } + pub(crate) use metric_ok; } From 0f164b62d5c4b36d9040d4ef933eeb1cb97a7359 Mon Sep 17 00:00:00 2001 From: Billy Chan <30400950+billy1624@users.noreply.github.com> Date: Fri, 10 Dec 2021 23:41:43 +0800 Subject: [PATCH 11/36] Fix related & linked with enum columns (#376) * Fix related & linked with enum columns * Add test cases --- src/entity/link.rs | 2 +- src/query/combine.rs | 30 +- src/query/join.rs | 25 +- tests/active_enum_tests.rs | 565 ++++++++++++++++++ tests/common/features/active_enum.rs | 51 +- tests/common/features/active_enum_child.rs | 43 ++ tests/common/features/mod.rs | 4 + tests/common/features/schema.rs | 59 +- tests/common/features/sea_orm_active_enums.rs | 28 + 9 files changed, 751 insertions(+), 56 deletions(-) create mode 100644 tests/common/features/active_enum_child.rs create mode 100644 tests/common/features/sea_orm_active_enums.rs diff --git a/src/entity/link.rs b/src/entity/link.rs index b929624d..4d91b8a0 100644 --- a/src/entity/link.rs +++ b/src/entity/link.rs @@ -30,7 +30,7 @@ pub trait Linked { select.query().join_as( JoinType::InnerJoin, - unpack_table_ref(&rel.from_tbl), + rel.from_tbl, SeaRc::clone(&from_tbl), join_tbl_on_condition(from_tbl, to_tbl, rel.from_col, rel.to_col), ); diff --git a/src/query/combine.rs b/src/query/combine.rs index a3dcc275..2baf3fa2 100644 --- a/src/query/combine.rs +++ b/src/query/combine.rs @@ -1,9 +1,12 @@ use crate::{ - EntityTrait, IdenStatic, IntoSimpleExpr, Iterable, QueryTrait, Select, SelectTwo, SelectTwoMany, + ColumnTrait, EntityTrait, IdenStatic, IntoSimpleExpr, Iterable, QueryTrait, Select, SelectTwo, + SelectTwoMany, }; use core::marker::PhantomData; pub use sea_query::JoinType; -use sea_query::{Alias, ColumnRef, Iden, Order, SeaRc, SelectExpr, SelectStatement, SimpleExpr}; +use sea_query::{ + Alias, ColumnRef, DynIden, Expr, Iden, Order, SeaRc, SelectExpr, SelectStatement, SimpleExpr, +}; macro_rules! select_def { ( $ident: ident, $str: expr ) => { @@ -42,10 +45,17 @@ where None => { let col = match &sel.expr { SimpleExpr::Column(col_ref) => match &col_ref { - ColumnRef::Column(col) => col, - ColumnRef::TableColumn(_, col) => col, + ColumnRef::Column(col) | ColumnRef::TableColumn(_, col) => col, }, - _ => panic!("cannot apply alias for expr other than Column"), + SimpleExpr::AsEnum(_, simple_expr) => match simple_expr.as_ref() { + SimpleExpr::Column(col_ref) => match &col_ref { + ColumnRef::Column(col) | ColumnRef::TableColumn(_, col) => col, + }, + _ => { + panic!("cannot apply alias for AsEnum with expr other than Column") + } + }, + _ => panic!("cannot apply alias for expr other than Column or AsEnum"), }; let alias = format!("{}{}", pre, col.to_string().as_str()); sel.alias = Some(SeaRc::new(Alias::new(&alias))); @@ -128,10 +138,18 @@ where F: EntityTrait, S: QueryTrait, { + let text_type = SeaRc::new(Alias::new("text")) as DynIden; for col in ::iter() { + let col_def = col.def(); + let col_type = col_def.get_column_type(); let alias = format!("{}{}", SelectB.as_str(), col.as_str()); + let expr = Expr::expr(col.into_simple_expr()); + let expr = match col_type.get_enum_name() { + Some(_) => expr.as_enum(text_type.clone()), + None => expr.into(), + }; selector.query().expr(SelectExpr { - expr: col.into_simple_expr(), + expr, alias: Some(SeaRc::new(Alias::new(&alias))), }); } diff --git a/src/query/join.rs b/src/query/join.rs index 8fb4e0e6..01f1dbd0 100644 --- a/src/query/join.rs +++ b/src/query/join.rs @@ -1,9 +1,9 @@ use crate::{ - join_tbl_on_condition, unpack_table_ref, EntityTrait, IdenStatic, Iterable, Linked, - QuerySelect, Related, Select, SelectA, SelectB, SelectTwo, SelectTwoMany, + join_tbl_on_condition, unpack_table_ref, ColumnTrait, EntityTrait, IdenStatic, Iterable, + Linked, QuerySelect, Related, Select, SelectA, SelectB, SelectTwo, SelectTwoMany, }; pub use sea_query::JoinType; -use sea_query::{Alias, Expr, IntoIden, SeaRc, SelectExpr}; +use sea_query::{Alias, DynIden, Expr, IntoIden, SeaRc, SelectExpr}; impl Select where @@ -79,21 +79,28 @@ where slf.query().join_as( JoinType::LeftJoin, - unpack_table_ref(&rel.to_tbl), + rel.to_tbl, SeaRc::clone(&to_tbl), join_tbl_on_condition(from_tbl, to_tbl, rel.from_col, rel.to_col), ); } slf = slf.apply_alias(SelectA.as_str()); + let text_type = SeaRc::new(Alias::new("text")) as DynIden; let mut select_two = SelectTwo::new_without_prepare(slf.query); for col in ::iter() { + let col_def = col.def(); + let col_type = col_def.get_column_type(); let alias = format!("{}{}", SelectB.as_str(), col.as_str()); + let expr = Expr::tbl( + Alias::new(&format!("r{}", l.link().len() - 1)).into_iden(), + col.into_iden(), + ); + let expr = match col_type.get_enum_name() { + Some(_) => expr.as_enum(text_type.clone()), + None => expr.into(), + }; select_two.query().expr(SelectExpr { - expr: Expr::tbl( - Alias::new(&format!("r{}", l.link().len() - 1)).into_iden(), - col.into_iden(), - ) - .into(), + expr, alias: Some(SeaRc::new(Alias::new(&alias))), }); } diff --git a/tests/active_enum_tests.rs b/tests/active_enum_tests.rs index aaad419b..79db6761 100644 --- a/tests/active_enum_tests.rs +++ b/tests/active_enum_tests.rs @@ -1,6 +1,9 @@ pub mod common; +use active_enum::Entity as ActiveEnum; +use active_enum_child::Entity as ActiveEnumChild; pub use common::{features::*, setup::*, TestContext}; +use pretty_assertions::assert_eq; use sea_orm::{entity::prelude::*, entity::*, DatabaseConnection}; #[sea_orm_macros::test] @@ -13,6 +16,9 @@ async fn main() -> Result<(), DbErr> { let ctx = TestContext::new("active_enum_tests").await; create_tables(&ctx.db).await?; insert_active_enum(&ctx.db).await?; + insert_active_enum_child(&ctx.db).await?; + find_related_active_enum(&ctx.db).await?; + find_linked_active_enum(&ctx.db).await?; ctx.delete().await; Ok(()) @@ -90,3 +96,562 @@ pub async fn insert_active_enum(db: &DatabaseConnection) -> Result<(), DbErr> { Ok(()) } + +pub async fn insert_active_enum_child(db: &DatabaseConnection) -> Result<(), DbErr> { + use active_enum_child::*; + + active_enum::ActiveModel { + category: Set(Some(Category::Small)), + color: Set(Some(Color::White)), + tea: Set(Some(Tea::BreakfastTea)), + ..Default::default() + } + .insert(db) + .await?; + + let am = ActiveModel { + parent_id: Set(2), + category: Set(None), + color: Set(None), + tea: Set(None), + ..Default::default() + } + .insert(db) + .await?; + + let model = Entity::find().one(db).await?.unwrap(); + assert_eq!( + model, + Model { + id: 1, + parent_id: 2, + category: None, + color: None, + tea: None, + } + ); + assert_eq!( + model, + Entity::find() + .filter(Column::Id.is_not_null()) + .filter(Column::Category.is_null()) + .filter(Column::Color.is_null()) + .filter(Column::Tea.is_null()) + .one(db) + .await? + .unwrap() + ); + + ActiveModel { + category: Set(Some(Category::Big)), + color: Set(Some(Color::Black)), + tea: Set(Some(Tea::EverydayTea)), + ..am + } + .save(db) + .await?; + + let model = Entity::find().one(db).await?.unwrap(); + assert_eq!( + model, + Model { + id: 1, + parent_id: 2, + category: Some(Category::Big), + color: Some(Color::Black), + tea: Some(Tea::EverydayTea), + } + ); + assert_eq!( + model, + Entity::find() + .filter(Column::Id.eq(1)) + .filter(Column::Category.eq(Category::Big)) + .filter(Column::Color.eq(Color::Black)) + .filter(Column::Tea.eq(Tea::EverydayTea)) + .one(db) + .await? + .unwrap() + ); + + Ok(()) +} + +pub async fn find_related_active_enum(db: &DatabaseConnection) -> Result<(), DbErr> { + assert_eq!( + active_enum::Model { + id: 2, + category: None, + color: None, + tea: None, + } + .find_related(ActiveEnumChild) + .all(db) + .await?, + vec![active_enum_child::Model { + id: 1, + parent_id: 2, + category: Some(Category::Big), + color: Some(Color::Black), + tea: Some(Tea::EverydayTea), + }] + ); + assert_eq!( + ActiveEnum::find() + .find_with_related(ActiveEnumChild) + .all(db) + .await?, + vec![( + active_enum::Model { + id: 2, + category: Some(Category::Small), + color: Some(Color::White), + tea: Some(Tea::BreakfastTea), + }, + vec![active_enum_child::Model { + id: 1, + parent_id: 2, + category: Some(Category::Big), + color: Some(Color::Black), + tea: Some(Tea::EverydayTea), + }] + )] + ); + assert_eq!( + ActiveEnum::find() + .find_also_related(ActiveEnumChild) + .all(db) + .await?, + vec![( + active_enum::Model { + id: 2, + category: Some(Category::Small), + color: Some(Color::White), + tea: Some(Tea::BreakfastTea), + }, + Some(active_enum_child::Model { + id: 1, + parent_id: 2, + category: Some(Category::Big), + color: Some(Color::Black), + tea: Some(Tea::EverydayTea), + }) + )] + ); + + assert_eq!( + active_enum_child::Model { + id: 1, + parent_id: 2, + category: None, + color: None, + tea: None, + } + .find_related(ActiveEnum) + .all(db) + .await?, + vec![active_enum::Model { + id: 2, + category: Some(Category::Small), + color: Some(Color::White), + tea: Some(Tea::BreakfastTea), + }] + ); + assert_eq!( + ActiveEnumChild::find() + .find_with_related(ActiveEnum) + .all(db) + .await?, + vec![( + active_enum_child::Model { + id: 1, + parent_id: 2, + category: Some(Category::Big), + color: Some(Color::Black), + tea: Some(Tea::EverydayTea), + }, + vec![active_enum::Model { + id: 2, + category: Some(Category::Small), + color: Some(Color::White), + tea: Some(Tea::BreakfastTea), + }] + )] + ); + assert_eq!( + ActiveEnumChild::find() + .find_also_related(ActiveEnum) + .all(db) + .await?, + vec![( + active_enum_child::Model { + id: 1, + parent_id: 2, + category: Some(Category::Big), + color: Some(Color::Black), + tea: Some(Tea::EverydayTea), + }, + Some(active_enum::Model { + id: 2, + category: Some(Category::Small), + color: Some(Color::White), + tea: Some(Tea::BreakfastTea), + }) + )] + ); + + Ok(()) +} + +pub async fn find_linked_active_enum(db: &DatabaseConnection) -> Result<(), DbErr> { + assert_eq!( + active_enum::Model { + id: 2, + category: None, + color: None, + tea: None, + } + .find_linked(active_enum::ActiveEnumChildLink) + .all(db) + .await?, + vec![active_enum_child::Model { + id: 1, + parent_id: 2, + category: Some(Category::Big), + color: Some(Color::Black), + tea: Some(Tea::EverydayTea), + }] + ); + assert_eq!( + ActiveEnum::find() + .find_also_linked(active_enum::ActiveEnumChildLink) + .all(db) + .await?, + vec![( + active_enum::Model { + id: 2, + category: Some(Category::Small), + color: Some(Color::White), + tea: Some(Tea::BreakfastTea), + }, + Some(active_enum_child::Model { + id: 1, + parent_id: 2, + category: Some(Category::Big), + color: Some(Color::Black), + tea: Some(Tea::EverydayTea), + }) + )] + ); + + assert_eq!( + active_enum_child::Model { + id: 1, + parent_id: 2, + category: None, + color: None, + tea: None, + } + .find_linked(active_enum_child::ActiveEnumLink) + .all(db) + .await?, + vec![active_enum::Model { + id: 2, + category: Some(Category::Small), + color: Some(Color::White), + tea: Some(Tea::BreakfastTea), + }] + ); + assert_eq!( + ActiveEnumChild::find() + .find_also_linked(active_enum_child::ActiveEnumLink) + .all(db) + .await?, + vec![( + active_enum_child::Model { + id: 1, + parent_id: 2, + category: Some(Category::Big), + color: Some(Color::Black), + tea: Some(Tea::EverydayTea), + }, + Some(active_enum::Model { + id: 2, + category: Some(Category::Small), + color: Some(Color::White), + tea: Some(Tea::BreakfastTea), + }) + )] + ); + + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + use pretty_assertions::assert_eq; + use sea_orm::{DbBackend, QueryTrait}; + + #[test] + fn active_enum_find_related() { + let active_enum_model = active_enum::Model { + id: 1, + category: None, + color: None, + tea: None, + }; + let select = active_enum_model.find_related(ActiveEnumChild); + assert_eq!( + select.build(DbBackend::MySql).to_string(), + select.build(DbBackend::Sqlite).to_string(), + ); + assert_eq!( + select.build(DbBackend::MySql).to_string(), + [ + "SELECT `active_enum_child`.`id`, `active_enum_child`.`parent_id`, `active_enum_child`.`category`, `active_enum_child`.`color`, `active_enum_child`.`tea`", + "FROM `active_enum_child`", + "INNER JOIN `active_enum` ON `active_enum`.`id` = `active_enum_child`.`parent_id`", + "WHERE `active_enum`.`id` = 1", + ] + .join(" ") + ); + assert_eq!( + select.build(DbBackend::Postgres).to_string(), + [ + r#"SELECT "active_enum_child"."id", "active_enum_child"."parent_id", "active_enum_child"."category", "active_enum_child"."color", CAST("active_enum_child"."tea" AS text)"#, + r#"FROM "public"."active_enum_child""#, + r#"INNER JOIN "public"."active_enum" ON "active_enum"."id" = "active_enum_child"."parent_id""#, + r#"WHERE "active_enum"."id" = 1"#, + ] + .join(" ") + ); + + let select = ActiveEnum::find().find_also_related(ActiveEnumChild); + assert_eq!( + select.build(DbBackend::MySql).to_string(), + select.build(DbBackend::Sqlite).to_string(), + ); + assert_eq!( + select + .build(DbBackend::MySql) + .to_string(), + [ + "SELECT `active_enum`.`id` AS `A_id`, `active_enum`.`category` AS `A_category`, `active_enum`.`color` AS `A_color`, `active_enum`.`tea` AS `A_tea`,", + "`active_enum_child`.`id` AS `B_id`, `active_enum_child`.`parent_id` AS `B_parent_id`, `active_enum_child`.`category` AS `B_category`, `active_enum_child`.`color` AS `B_color`, `active_enum_child`.`tea` AS `B_tea`", + "FROM `active_enum`", + "LEFT JOIN `active_enum_child` ON `active_enum`.`id` = `active_enum_child`.`parent_id`", + ] + .join(" ") + ); + assert_eq!( + select + .build(DbBackend::Postgres) + .to_string(), + [ + r#"SELECT "active_enum"."id" AS "A_id", "active_enum"."category" AS "A_category", "active_enum"."color" AS "A_color", CAST("active_enum"."tea" AS text) AS "A_tea","#, + r#""active_enum_child"."id" AS "B_id", "active_enum_child"."parent_id" AS "B_parent_id", "active_enum_child"."category" AS "B_category", "active_enum_child"."color" AS "B_color", CAST("active_enum_child"."tea" AS text) AS "B_tea""#, + r#"FROM "public"."active_enum""#, + r#"LEFT JOIN "public"."active_enum_child" ON "active_enum"."id" = "active_enum_child"."parent_id""#, + ] + .join(" ") + ); + } + + #[test] + fn active_enum_find_linked() { + let active_enum_model = active_enum::Model { + id: 1, + category: None, + color: None, + tea: None, + }; + let select = active_enum_model.find_linked(active_enum::ActiveEnumChildLink); + assert_eq!( + select.build(DbBackend::MySql).to_string(), + select.build(DbBackend::Sqlite).to_string(), + ); + assert_eq!( + select.build(DbBackend::MySql).to_string(), + [ + "SELECT `active_enum_child`.`id`, `active_enum_child`.`parent_id`, `active_enum_child`.`category`, `active_enum_child`.`color`, `active_enum_child`.`tea`", + "FROM `active_enum_child`", + "INNER JOIN `active_enum` AS `r0` ON `r0`.`id` = `active_enum_child`.`parent_id`", + "WHERE `r0`.`id` = 1", + ] + .join(" ") + ); + assert_eq!( + select.build(DbBackend::Postgres).to_string(), + [ + r#"SELECT "active_enum_child"."id", "active_enum_child"."parent_id", "active_enum_child"."category", "active_enum_child"."color", CAST("active_enum_child"."tea" AS text)"#, + r#"FROM "public"."active_enum_child""#, + r#"INNER JOIN "public"."active_enum" AS "r0" ON "r0"."id" = "active_enum_child"."parent_id""#, + r#"WHERE "r0"."id" = 1"#, + ] + .join(" ") + ); + + let select = ActiveEnum::find().find_also_linked(active_enum::ActiveEnumChildLink); + assert_eq!( + select.build(DbBackend::MySql).to_string(), + select.build(DbBackend::Sqlite).to_string(), + ); + assert_eq!( + select + .build(DbBackend::MySql) + .to_string(), + [ + "SELECT `active_enum`.`id` AS `A_id`, `active_enum`.`category` AS `A_category`, `active_enum`.`color` AS `A_color`, `active_enum`.`tea` AS `A_tea`,", + "`r0`.`id` AS `B_id`, `r0`.`parent_id` AS `B_parent_id`, `r0`.`category` AS `B_category`, `r0`.`color` AS `B_color`, `r0`.`tea` AS `B_tea`", + "FROM `active_enum`", + "LEFT JOIN `active_enum_child` AS `r0` ON `active_enum`.`id` = `r0`.`parent_id`", + ] + .join(" ") + ); + assert_eq!( + select + .build(DbBackend::Postgres) + .to_string(), + [ + r#"SELECT "active_enum"."id" AS "A_id", "active_enum"."category" AS "A_category", "active_enum"."color" AS "A_color", CAST("active_enum"."tea" AS text) AS "A_tea","#, + r#""r0"."id" AS "B_id", "r0"."parent_id" AS "B_parent_id", "r0"."category" AS "B_category", "r0"."color" AS "B_color", CAST("r0"."tea" AS text) AS "B_tea""#, + r#"FROM "public"."active_enum""#, + r#"LEFT JOIN "public"."active_enum_child" AS "r0" ON "active_enum"."id" = "r0"."parent_id""#, + ] + .join(" ") + ); + } + + #[test] + fn active_enum_child_find_related() { + let active_enum_child_model = active_enum_child::Model { + id: 1, + parent_id: 2, + category: None, + color: None, + tea: None, + }; + let select = active_enum_child_model.find_related(ActiveEnum); + assert_eq!( + select.build(DbBackend::MySql).to_string(), + select.build(DbBackend::Sqlite).to_string(), + ); + assert_eq!( + select.build(DbBackend::MySql).to_string(), + [ + "SELECT `active_enum`.`id`, `active_enum`.`category`, `active_enum`.`color`, `active_enum`.`tea`", + "FROM `active_enum`", + "INNER JOIN `active_enum_child` ON `active_enum_child`.`parent_id` = `active_enum`.`id`", + "WHERE `active_enum_child`.`id` = 1", + ] + .join(" ") + ); + assert_eq!( + select.build(DbBackend::Postgres).to_string(), + [ + r#"SELECT "active_enum"."id", "active_enum"."category", "active_enum"."color", CAST("active_enum"."tea" AS text)"#, + r#"FROM "public"."active_enum""#, + r#"INNER JOIN "public"."active_enum_child" ON "active_enum_child"."parent_id" = "active_enum"."id""#, + r#"WHERE "active_enum_child"."id" = 1"#, + ] + .join(" ") + ); + + let select = ActiveEnumChild::find().find_also_related(ActiveEnum); + assert_eq!( + select.build(DbBackend::MySql).to_string(), + select.build(DbBackend::Sqlite).to_string(), + ); + assert_eq!( + select + .build(DbBackend::MySql) + .to_string(), + [ + "SELECT `active_enum_child`.`id` AS `A_id`, `active_enum_child`.`parent_id` AS `A_parent_id`, `active_enum_child`.`category` AS `A_category`, `active_enum_child`.`color` AS `A_color`, `active_enum_child`.`tea` AS `A_tea`,", + "`active_enum`.`id` AS `B_id`, `active_enum`.`category` AS `B_category`, `active_enum`.`color` AS `B_color`, `active_enum`.`tea` AS `B_tea`", + "FROM `active_enum_child`", + "LEFT JOIN `active_enum` ON `active_enum_child`.`parent_id` = `active_enum`.`id`", + ] + .join(" ") + ); + assert_eq!( + select + .build(DbBackend::Postgres) + .to_string(), + [ + r#"SELECT "active_enum_child"."id" AS "A_id", "active_enum_child"."parent_id" AS "A_parent_id", "active_enum_child"."category" AS "A_category", "active_enum_child"."color" AS "A_color", CAST("active_enum_child"."tea" AS text) AS "A_tea","#, + r#""active_enum"."id" AS "B_id", "active_enum"."category" AS "B_category", "active_enum"."color" AS "B_color", CAST("active_enum"."tea" AS text) AS "B_tea""#, + r#"FROM "public"."active_enum_child""#, + r#"LEFT JOIN "public"."active_enum" ON "active_enum_child"."parent_id" = "active_enum"."id""#, + ] + .join(" ") + ); + } + + #[test] + fn active_enum_child_find_linked() { + let active_enum_child_model = active_enum_child::Model { + id: 1, + parent_id: 2, + category: None, + color: None, + tea: None, + }; + let select = active_enum_child_model.find_linked(active_enum_child::ActiveEnumLink); + assert_eq!( + select.build(DbBackend::MySql).to_string(), + select.build(DbBackend::Sqlite).to_string(), + ); + assert_eq!( + select.build(DbBackend::MySql).to_string(), + [ + "SELECT `active_enum`.`id`, `active_enum`.`category`, `active_enum`.`color`, `active_enum`.`tea`", + "FROM `active_enum`", + "INNER JOIN `active_enum_child` AS `r0` ON `r0`.`parent_id` = `active_enum`.`id`", + "WHERE `r0`.`id` = 1", + ] + .join(" ") + ); + assert_eq!( + select.build(DbBackend::Postgres).to_string(), + [ + r#"SELECT "active_enum"."id", "active_enum"."category", "active_enum"."color", CAST("active_enum"."tea" AS text)"#, + r#"FROM "public"."active_enum""#, + r#"INNER JOIN "public"."active_enum_child" AS "r0" ON "r0"."parent_id" = "active_enum"."id""#, + r#"WHERE "r0"."id" = 1"#, + ] + .join(" ") + ); + + let select = ActiveEnumChild::find().find_also_linked(active_enum_child::ActiveEnumLink); + assert_eq!( + select.build(DbBackend::MySql).to_string(), + select.build(DbBackend::Sqlite).to_string(), + ); + assert_eq!( + select + .build(DbBackend::MySql) + .to_string(), + [ + "SELECT `active_enum_child`.`id` AS `A_id`, `active_enum_child`.`parent_id` AS `A_parent_id`, `active_enum_child`.`category` AS `A_category`, `active_enum_child`.`color` AS `A_color`, `active_enum_child`.`tea` AS `A_tea`,", + "`r0`.`id` AS `B_id`, `r0`.`category` AS `B_category`, `r0`.`color` AS `B_color`, `r0`.`tea` AS `B_tea`", + "FROM `active_enum_child`", + "LEFT JOIN `active_enum` AS `r0` ON `active_enum_child`.`parent_id` = `r0`.`id`", + ] + .join(" ") + ); + assert_eq!( + select + .build(DbBackend::Postgres) + .to_string(), + [ + r#"SELECT "active_enum_child"."id" AS "A_id", "active_enum_child"."parent_id" AS "A_parent_id", "active_enum_child"."category" AS "A_category", "active_enum_child"."color" AS "A_color", CAST("active_enum_child"."tea" AS text) AS "A_tea","#, + r#""r0"."id" AS "B_id", "r0"."category" AS "B_category", "r0"."color" AS "B_color", CAST("r0"."tea" AS text) AS "B_tea""#, + r#"FROM "public"."active_enum_child""#, + r#"LEFT JOIN "public"."active_enum" AS "r0" ON "active_enum_child"."parent_id" = "r0"."id""#, + ] + .join(" ") + ); + } +} diff --git a/tests/common/features/active_enum.rs b/tests/common/features/active_enum.rs index 01945993..01422973 100644 --- a/tests/common/features/active_enum.rs +++ b/tests/common/features/active_enum.rs @@ -1,3 +1,4 @@ +use super::sea_orm_active_enums::*; use sea_orm::entity::prelude::*; #[derive(Clone, Debug, PartialEq, DeriveEntityModel)] @@ -11,33 +12,27 @@ pub struct Model { } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation {} +pub enum Relation { + #[sea_orm(has_many = "super::active_enum_child::Entity")] + ActiveEnumChild, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::ActiveEnumChild.def() + } +} + +pub struct ActiveEnumChildLink; + +impl Linked for ActiveEnumChildLink { + type FromEntity = Entity; + + type ToEntity = super::active_enum_child::Entity; + + fn link(&self) -> Vec { + vec![Relation::ActiveEnumChild.def()] + } +} impl ActiveModelBehavior for ActiveModel {} - -#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum)] -#[sea_orm(rs_type = "String", db_type = "String(Some(1))")] -pub enum Category { - #[sea_orm(string_value = "B")] - Big, - #[sea_orm(string_value = "S")] - Small, -} - -#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum)] -#[sea_orm(rs_type = "i32", db_type = "Integer")] -pub enum Color { - #[sea_orm(num_value = 0)] - Black, - #[sea_orm(num_value = 1)] - White, -} - -#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum)] -#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "tea")] -pub enum Tea { - #[sea_orm(string_value = "EverydayTea")] - EverydayTea, - #[sea_orm(string_value = "BreakfastTea")] - BreakfastTea, -} diff --git a/tests/common/features/active_enum_child.rs b/tests/common/features/active_enum_child.rs new file mode 100644 index 00000000..9c98b280 --- /dev/null +++ b/tests/common/features/active_enum_child.rs @@ -0,0 +1,43 @@ +use super::sea_orm_active_enums::*; +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(schema_name = "public", table_name = "active_enum_child")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub parent_id: i32, + pub category: Option, + pub color: Option, + pub tea: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::active_enum::Entity", + from = "Column::ParentId", + to = "super::active_enum::Column::Id" + )] + ActiveEnum, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::ActiveEnum.def() + } +} + +pub struct ActiveEnumLink; + +impl Linked for ActiveEnumLink { + type FromEntity = Entity; + + type ToEntity = super::active_enum::Entity; + + fn link(&self) -> Vec { + vec![Relation::ActiveEnum.def()] + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/tests/common/features/mod.rs b/tests/common/features/mod.rs index e354292b..ea880fd2 100644 --- a/tests/common/features/mod.rs +++ b/tests/common/features/mod.rs @@ -1,15 +1,19 @@ pub mod active_enum; +pub mod active_enum_child; pub mod applog; pub mod byte_primary_key; pub mod metadata; pub mod repository; pub mod schema; +pub mod sea_orm_active_enums; pub mod self_join; pub use active_enum::Entity as ActiveEnum; +pub use active_enum_child::Entity as ActiveEnumChild; pub use applog::Entity as Applog; pub use byte_primary_key::Entity as BytePrimaryKey; pub use metadata::Entity as Metadata; pub use repository::Entity as Repository; pub use schema::*; +pub use sea_orm_active_enums::*; pub use self_join::Entity as SelfJoin; diff --git a/tests/common/features/schema.rs b/tests/common/features/schema.rs index 5184c263..91712c91 100644 --- a/tests/common/features/schema.rs +++ b/tests/common/features/schema.rs @@ -9,12 +9,25 @@ use sea_orm::{ use sea_query::{extension::postgres::Type, Alias, ColumnDef, ForeignKeyCreateStatement}; pub async fn create_tables(db: &DatabaseConnection) -> Result<(), DbErr> { + let db_backend = db.get_database_backend(); + create_log_table(db).await?; create_metadata_table(db).await?; create_repository_table(db).await?; create_self_join_table(db).await?; create_byte_primary_key_table(db).await?; + + let create_enum_stmts = match db_backend { + DbBackend::MySql | DbBackend::Sqlite => Vec::new(), + DbBackend::Postgres => vec![Type::create() + .as_enum(Alias::new("tea")) + .values(vec![Alias::new("EverydayTea"), Alias::new("BreakfastTea")]) + .to_owned()], + }; + create_enum(db, &create_enum_stmts, ActiveEnum).await?; + create_active_enum_table(db).await?; + create_active_enum_child_table(db).await?; Ok(()) } @@ -127,18 +140,6 @@ pub async fn create_byte_primary_key_table(db: &DbConn) -> Result Result { - let db_backend = db.get_database_backend(); - - let create_enum_stmts = match db_backend { - DbBackend::MySql | DbBackend::Sqlite => Vec::new(), - DbBackend::Postgres => vec![Type::create() - .as_enum(Alias::new("tea")) - .values(vec![Alias::new("EverydayTea"), Alias::new("BreakfastTea")]) - .to_owned()], - }; - - create_enum(db, &create_enum_stmts, ActiveEnum).await?; - let create_table_stmt = sea_query::Table::create() .table(active_enum::Entity.table_ref()) .col( @@ -158,3 +159,37 @@ pub async fn create_active_enum_table(db: &DbConn) -> Result create_table(db, &create_table_stmt, ActiveEnum).await } + +pub async fn create_active_enum_child_table(db: &DbConn) -> Result { + let create_table_stmt = sea_query::Table::create() + .table(active_enum_child::Entity.table_ref()) + .col( + ColumnDef::new(active_enum_child::Column::Id) + .integer() + .not_null() + .auto_increment() + .primary_key(), + ) + .col( + ColumnDef::new(active_enum_child::Column::ParentId) + .integer() + .not_null(), + ) + .col(ColumnDef::new(active_enum_child::Column::Category).string_len(1)) + .col(ColumnDef::new(active_enum_child::Column::Color).integer()) + .col( + ColumnDef::new(active_enum_child::Column::Tea) + .enumeration("tea", vec!["EverydayTea", "BreakfastTea"]), + ) + .foreign_key( + ForeignKeyCreateStatement::new() + .name("fk-active_enum_child-active_enum") + .from_tbl(ActiveEnumChild) + .from_col(active_enum_child::Column::ParentId) + .to_tbl(ActiveEnum) + .to_col(active_enum::Column::Id), + ) + .to_owned(); + + create_table(db, &create_table_stmt, ActiveEnumChild).await +} diff --git a/tests/common/features/sea_orm_active_enums.rs b/tests/common/features/sea_orm_active_enums.rs new file mode 100644 index 00000000..00bff5b0 --- /dev/null +++ b/tests/common/features/sea_orm_active_enums.rs @@ -0,0 +1,28 @@ +use sea_orm::entity::prelude::*; + +#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum)] +#[sea_orm(rs_type = "String", db_type = "String(Some(1))")] +pub enum Category { + #[sea_orm(string_value = "B")] + Big, + #[sea_orm(string_value = "S")] + Small, +} + +#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum)] +#[sea_orm(rs_type = "i32", db_type = "Integer")] +pub enum Color { + #[sea_orm(num_value = 0)] + Black, + #[sea_orm(num_value = 1)] + White, +} + +#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum)] +#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "tea")] +pub enum Tea { + #[sea_orm(string_value = "EverydayTea")] + EverydayTea, + #[sea_orm(string_value = "BreakfastTea")] + BreakfastTea, +} From a9f6275a9e93961b720e3afa82c7b7e2eff9218d Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Sat, 11 Dec 2021 12:36:27 +0800 Subject: [PATCH 12/36] Run timestamp_tests for all databases --- tests/timestamp_tests.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/timestamp_tests.rs b/tests/timestamp_tests.rs index f0d6ca77..cad35270 100644 --- a/tests/timestamp_tests.rs +++ b/tests/timestamp_tests.rs @@ -4,7 +4,11 @@ pub use common::{features::*, setup::*, TestContext}; use sea_orm::{entity::prelude::*, DatabaseConnection, IntoActiveModel}; #[sea_orm_macros::test] -#[cfg(feature = "sqlx-postgres")] +#[cfg(any( + feature = "sqlx-mysql", + feature = "sqlx-sqlite", + feature = "sqlx-postgres" +))] async fn main() -> Result<(), DbErr> { let ctx = TestContext::new("bakery_chain_schema_timestamp_tests").await; create_tables(&ctx.db).await?; From b9fe878542ff5a52592a164807048aa4f68d472c Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Sat, 11 Dec 2021 12:37:45 +0800 Subject: [PATCH 13/36] Handling MySQL & SQLite timestamp columns --- src/executor/query.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/executor/query.rs b/src/executor/query.rs index f5070384..c76d7bcc 100644 --- a/src/executor/query.rs +++ b/src/executor/query.rs @@ -199,15 +199,20 @@ macro_rules! try_getable_mysql { }; } -macro_rules! try_getable_postgres { +macro_rules! try_getable_date_time { ( $type: ty ) => { impl TryGetable for $type { fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result { let _column = format!("{}{}", pre, col); match &res.row { #[cfg(feature = "sqlx-mysql")] - QueryResultRow::SqlxMySql(_) => { - panic!("{} unsupported by sqlx-mysql", stringify!($type)) + QueryResultRow::SqlxMySql(row) => { + use chrono::{DateTime, Utc}; + use sqlx::Row; + row.try_get::>, _>(_column.as_str()) + .map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e))) + .and_then(|opt| opt.ok_or(TryGetError::Null)) + .map(|v| v.into()) } #[cfg(feature = "sqlx-postgres")] QueryResultRow::SqlxPostgres(row) => { @@ -217,8 +222,13 @@ macro_rules! try_getable_postgres { .and_then(|opt| opt.ok_or(TryGetError::Null)) } #[cfg(feature = "sqlx-sqlite")] - QueryResultRow::SqlxSqlite(_) => { - panic!("{} unsupported by sqlx-sqlite", stringify!($type)) + QueryResultRow::SqlxSqlite(row) => { + use chrono::{DateTime, Utc}; + use sqlx::Row; + row.try_get::>, _>(_column.as_str()) + .map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e))) + .and_then(|opt| opt.ok_or(TryGetError::Null)) + .map(|v| v.into()) } #[cfg(feature = "mock")] #[allow(unused_variables)] @@ -259,7 +269,7 @@ try_getable_all!(chrono::NaiveTime); try_getable_all!(chrono::NaiveDateTime); #[cfg(feature = "with-chrono")] -try_getable_postgres!(chrono::DateTime); +try_getable_date_time!(chrono::DateTime); #[cfg(feature = "with-rust_decimal")] use rust_decimal::Decimal; From 8db9d10c12357fd69671c12f942f5b54600a2fe8 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sat, 11 Dec 2021 14:26:18 +0800 Subject: [PATCH 14/36] Bump sea-query --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 47f075eb..a715025e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ futures-util = { version = "^0.3" } log = { version = "^0.4", optional = true } rust_decimal = { version = "^1", optional = true } sea-orm-macros = { version = "^0.4.1", path = "sea-orm-macros", optional = true } -sea-query = { version = "^0.19.1", features = ["thread-safe"] } +sea-query = { version = "^0.19.4", features = ["thread-safe"] } sea-strum = { version = "^0.21", features = ["derive", "sea-orm"] } serde = { version = "^1.0", features = ["derive"] } serde_json = { version = "^1", optional = true } From 6767e8b8348e4c3c0f122b86d39393dec0f2f84c Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sun, 12 Dec 2021 22:45:34 +0800 Subject: [PATCH 15/36] sea-orm-codegen 0.4.2 --- sea-orm-codegen/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sea-orm-codegen/Cargo.toml b/sea-orm-codegen/Cargo.toml index 315fc17b..a4b0a57b 100644 --- a/sea-orm-codegen/Cargo.toml +++ b/sea-orm-codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sea-orm-codegen" -version = "0.4.1" +version = "0.4.2" authors = ["Billy Chan "] edition = "2021" description = "Code Generator for SeaORM" From 0ea4f4e9401e7a0a55e06bec4469a5925136f362 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sun, 12 Dec 2021 22:46:18 +0800 Subject: [PATCH 16/36] sea-orm-cli 0.4.2 --- sea-orm-cli/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sea-orm-cli/Cargo.toml b/sea-orm-cli/Cargo.toml index 3dc0fa61..6f67ccd6 100644 --- a/sea-orm-cli/Cargo.toml +++ b/sea-orm-cli/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "sea-orm-cli" -version = "0.4.1" +version = "0.4.2" authors = [ "Billy Chan " ] edition = "2021" description = "Command line utility for SeaORM" @@ -21,7 +21,7 @@ path = "src/main.rs" clap = { version = "^2.33.3" } dotenv = { version = "^0.15" } async-std = { version = "^1.9", features = [ "attributes" ] } -sea-orm-codegen = { version = "^0.4.1", path = "../sea-orm-codegen" } +sea-orm-codegen = { version = "^0.4.2", path = "../sea-orm-codegen" } sea-schema = { version = "^0.2.9", default-features = false, features = [ "debug-print", "sqlx-mysql", From 7327a00cb2ddd29d779eab95f8369593f6b85146 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sun, 12 Dec 2021 22:48:03 +0800 Subject: [PATCH 17/36] sea-orm-macros 0.4.2 --- sea-orm-macros/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sea-orm-macros/Cargo.toml b/sea-orm-macros/Cargo.toml index 6aa91c30..ff30ba7a 100644 --- a/sea-orm-macros/Cargo.toml +++ b/sea-orm-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sea-orm-macros" -version = "0.4.1" +version = "0.4.2" authors = [ "Billy Chan " ] edition = "2021" description = "Derive macros for SeaORM" From 5656c4981d954adf4790c43c882f27d86d7b1c8a Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sun, 12 Dec 2021 22:55:11 +0800 Subject: [PATCH 18/36] 0.4.2 --- CHANGELOG.md | 16 ++++++++++++++++ Cargo.toml | 4 ++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd9c5072..dfb7c4c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## 0.4.2 - 2021-12-12 + +### Fixed Issues +* Delete::many() doesn't work when schema_name is defined https://github.com/SeaQL/sea-orm/issues/362 +* find_with_related panic https://github.com/SeaQL/sea-orm/issues/374 +* How to define rust type of TIMESTAMP? https://github.com/SeaQL/sea-orm/issues/344 +* Add Table on the generated Column enum https://github.com/SeaQL/sea-orm/issues/356 + +### Merged PRs +* `Delete::many()` with `TableRef` by @billy1624 in https://github.com/SeaQL/sea-orm/pull/363 +* Fix related & linked with enum columns by @billy1624 in https://github.com/SeaQL/sea-orm/pull/376 +* Temporary Fix: Handling MySQL & SQLite timestamp columns by @billy1624 in https://github.com/SeaQL/sea-orm/pull/379 +* Add feature to generate table Iden by @Sytten in https://github.com/SeaQL/sea-orm/pull/360 + +**Full Changelog**: https://github.com/SeaQL/sea-orm/compare/0.4.1...0.4.2 + ## 0.4.1 - 2021-12-05 ### Fixed Issues diff --git a/Cargo.toml b/Cargo.toml index a715025e..bf6958f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = [".", "sea-orm-macros", "sea-orm-codegen"] [package] name = "sea-orm" -version = "0.4.1" +version = "0.4.2" authors = ["Chris Tsang "] edition = "2021" description = "🐚 An async & dynamic ORM for Rust" @@ -29,7 +29,7 @@ futures = { version = "^0.3" } futures-util = { version = "^0.3" } log = { version = "^0.4", optional = true } rust_decimal = { version = "^1", optional = true } -sea-orm-macros = { version = "^0.4.1", path = "sea-orm-macros", optional = true } +sea-orm-macros = { version = "^0.4.2", path = "sea-orm-macros", optional = true } sea-query = { version = "^0.19.4", features = ["thread-safe"] } sea-strum = { version = "^0.21", features = ["derive", "sea-orm"] } serde = { version = "^1.0", features = ["derive"] } From 66a005237cb547b415c6e23e19fdb87c56416c96 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Thu, 9 Dec 2021 13:24:19 +0800 Subject: [PATCH 19/36] Update sea-orm to depends on sea-query 0.20.0 --- Cargo.toml | 2 +- src/query/helper.rs | 12 +- src/schema/entity.rs | 11 - tests/active_enum_tests.rs | 272 ++++++++++++--------- tests/common/features/active_enum.rs | 3 +- tests/common/features/active_enum_child.rs | 3 +- 6 files changed, 164 insertions(+), 139 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bf6958f4..c7482eb4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ futures-util = { version = "^0.3" } log = { version = "^0.4", optional = true } rust_decimal = { version = "^1", optional = true } sea-orm-macros = { version = "^0.4.2", path = "sea-orm-macros", optional = true } -sea-query = { version = "^0.19.4", features = ["thread-safe"] } +sea-query = { version = "^0.20.0", features = ["thread-safe"] } sea-strum = { version = "^0.21", features = ["derive", "sea-orm"] } serde = { version = "^1.0", features = ["derive"] } serde_json = { version = "^1", optional = true } diff --git a/src/query/helper.rs b/src/query/helper.rs index ca51aae0..6fcd993c 100644 --- a/src/query/helper.rs +++ b/src/query/helper.rs @@ -465,10 +465,12 @@ pub(crate) fn join_tbl_on_condition( pub(crate) fn unpack_table_ref(table_ref: &TableRef) -> DynIden { match table_ref { - TableRef::Table(tbl) => SeaRc::clone(tbl), - TableRef::SchemaTable(_, tbl) => SeaRc::clone(tbl), - TableRef::TableAlias(tbl, _) => SeaRc::clone(tbl), - TableRef::SchemaTableAlias(_, tbl, _) => SeaRc::clone(tbl), - TableRef::SubQuery(_, tbl) => SeaRc::clone(tbl), + TableRef::Table(tbl) + | TableRef::SchemaTable(_, tbl) + | TableRef::DatabaseSchemaTable(_, _, tbl) + | TableRef::TableAlias(tbl, _) + | TableRef::SchemaTableAlias(_, tbl, _) + | TableRef::DatabaseSchemaTableAlias(_, _, tbl, _) + | TableRef::SubQuery(_, tbl) => SeaRc::clone(tbl), } } diff --git a/src/schema/entity.rs b/src/schema/entity.rs index 3e02c42c..cc185e69 100644 --- a/src/schema/entity.rs +++ b/src/schema/entity.rs @@ -184,17 +184,6 @@ mod tests { } } - #[test] - fn test_create_table_from_entity() { - for builder in [DbBackend::MySql, DbBackend::Sqlite] { - let schema = Schema::new(builder); - assert_eq!( - builder.build(&schema.create_table_from_entity(CakeFillingPrice)), - builder.build(&get_stmt().table(CakeFillingPrice).to_owned()) - ); - } - } - fn get_stmt() -> TableCreateStatement { Table::create() .col( diff --git a/tests/active_enum_tests.rs b/tests/active_enum_tests.rs index 79db6761..cb8e0092 100644 --- a/tests/active_enum_tests.rs +++ b/tests/active_enum_tests.rs @@ -402,20 +402,24 @@ mod tests { tea: None, }; let select = active_enum_model.find_related(ActiveEnumChild); - assert_eq!( - select.build(DbBackend::MySql).to_string(), - select.build(DbBackend::Sqlite).to_string(), - ); - assert_eq!( - select.build(DbBackend::MySql).to_string(), - [ - "SELECT `active_enum_child`.`id`, `active_enum_child`.`parent_id`, `active_enum_child`.`category`, `active_enum_child`.`color`, `active_enum_child`.`tea`", - "FROM `active_enum_child`", - "INNER JOIN `active_enum` ON `active_enum`.`id` = `active_enum_child`.`parent_id`", - "WHERE `active_enum`.`id` = 1", - ] - .join(" ") - ); + #[cfg(any(feature = "sqlx-mysql", feature = "sqlx-sqlite"))] + { + assert_eq!( + select.build(DbBackend::MySql).to_string(), + select.build(DbBackend::Sqlite).to_string(), + ); + assert_eq!( + select.build(DbBackend::MySql).to_string(), + [ + "SELECT `active_enum_child`.`id`, `active_enum_child`.`parent_id`, `active_enum_child`.`category`, `active_enum_child`.`color`, `active_enum_child`.`tea`", + "FROM `active_enum_child`", + "INNER JOIN `active_enum` ON `active_enum`.`id` = `active_enum_child`.`parent_id`", + "WHERE `active_enum`.`id` = 1", + ] + .join(" ") + ); + } + #[cfg(feature = "sqlx-postgres")] assert_eq!( select.build(DbBackend::Postgres).to_string(), [ @@ -428,22 +432,26 @@ mod tests { ); let select = ActiveEnum::find().find_also_related(ActiveEnumChild); - assert_eq!( - select.build(DbBackend::MySql).to_string(), - select.build(DbBackend::Sqlite).to_string(), - ); - assert_eq!( - select - .build(DbBackend::MySql) - .to_string(), - [ - "SELECT `active_enum`.`id` AS `A_id`, `active_enum`.`category` AS `A_category`, `active_enum`.`color` AS `A_color`, `active_enum`.`tea` AS `A_tea`,", - "`active_enum_child`.`id` AS `B_id`, `active_enum_child`.`parent_id` AS `B_parent_id`, `active_enum_child`.`category` AS `B_category`, `active_enum_child`.`color` AS `B_color`, `active_enum_child`.`tea` AS `B_tea`", - "FROM `active_enum`", - "LEFT JOIN `active_enum_child` ON `active_enum`.`id` = `active_enum_child`.`parent_id`", - ] - .join(" ") - ); + #[cfg(any(feature = "sqlx-mysql", feature = "sqlx-sqlite"))] + { + assert_eq!( + select.build(DbBackend::MySql).to_string(), + select.build(DbBackend::Sqlite).to_string(), + ); + assert_eq!( + select + .build(DbBackend::MySql) + .to_string(), + [ + "SELECT `active_enum`.`id` AS `A_id`, `active_enum`.`category` AS `A_category`, `active_enum`.`color` AS `A_color`, `active_enum`.`tea` AS `A_tea`,", + "`active_enum_child`.`id` AS `B_id`, `active_enum_child`.`parent_id` AS `B_parent_id`, `active_enum_child`.`category` AS `B_category`, `active_enum_child`.`color` AS `B_color`, `active_enum_child`.`tea` AS `B_tea`", + "FROM `active_enum`", + "LEFT JOIN `active_enum_child` ON `active_enum`.`id` = `active_enum_child`.`parent_id`", + ] + .join(" ") + ); + } + #[cfg(feature = "sqlx-postgres")] assert_eq!( select .build(DbBackend::Postgres) @@ -467,20 +475,24 @@ mod tests { tea: None, }; let select = active_enum_model.find_linked(active_enum::ActiveEnumChildLink); - assert_eq!( - select.build(DbBackend::MySql).to_string(), - select.build(DbBackend::Sqlite).to_string(), - ); - assert_eq!( - select.build(DbBackend::MySql).to_string(), - [ - "SELECT `active_enum_child`.`id`, `active_enum_child`.`parent_id`, `active_enum_child`.`category`, `active_enum_child`.`color`, `active_enum_child`.`tea`", - "FROM `active_enum_child`", - "INNER JOIN `active_enum` AS `r0` ON `r0`.`id` = `active_enum_child`.`parent_id`", - "WHERE `r0`.`id` = 1", - ] - .join(" ") - ); + #[cfg(any(feature = "sqlx-mysql", feature = "sqlx-sqlite"))] + { + assert_eq!( + select.build(DbBackend::MySql).to_string(), + select.build(DbBackend::Sqlite).to_string(), + ); + assert_eq!( + select.build(DbBackend::MySql).to_string(), + [ + "SELECT `active_enum_child`.`id`, `active_enum_child`.`parent_id`, `active_enum_child`.`category`, `active_enum_child`.`color`, `active_enum_child`.`tea`", + "FROM `active_enum_child`", + "INNER JOIN `active_enum` AS `r0` ON `r0`.`id` = `active_enum_child`.`parent_id`", + "WHERE `r0`.`id` = 1", + ] + .join(" ") + ); + } + #[cfg(feature = "sqlx-postgres")] assert_eq!( select.build(DbBackend::Postgres).to_string(), [ @@ -493,22 +505,26 @@ mod tests { ); let select = ActiveEnum::find().find_also_linked(active_enum::ActiveEnumChildLink); - assert_eq!( - select.build(DbBackend::MySql).to_string(), - select.build(DbBackend::Sqlite).to_string(), - ); - assert_eq!( - select - .build(DbBackend::MySql) - .to_string(), - [ - "SELECT `active_enum`.`id` AS `A_id`, `active_enum`.`category` AS `A_category`, `active_enum`.`color` AS `A_color`, `active_enum`.`tea` AS `A_tea`,", - "`r0`.`id` AS `B_id`, `r0`.`parent_id` AS `B_parent_id`, `r0`.`category` AS `B_category`, `r0`.`color` AS `B_color`, `r0`.`tea` AS `B_tea`", - "FROM `active_enum`", - "LEFT JOIN `active_enum_child` AS `r0` ON `active_enum`.`id` = `r0`.`parent_id`", - ] - .join(" ") - ); + #[cfg(any(feature = "sqlx-mysql", feature = "sqlx-sqlite"))] + { + assert_eq!( + select.build(DbBackend::MySql).to_string(), + select.build(DbBackend::Sqlite).to_string(), + ); + assert_eq!( + select + .build(DbBackend::MySql) + .to_string(), + [ + "SELECT `active_enum`.`id` AS `A_id`, `active_enum`.`category` AS `A_category`, `active_enum`.`color` AS `A_color`, `active_enum`.`tea` AS `A_tea`,", + "`r0`.`id` AS `B_id`, `r0`.`parent_id` AS `B_parent_id`, `r0`.`category` AS `B_category`, `r0`.`color` AS `B_color`, `r0`.`tea` AS `B_tea`", + "FROM `active_enum`", + "LEFT JOIN `active_enum_child` AS `r0` ON `active_enum`.`id` = `r0`.`parent_id`", + ] + .join(" ") + ); + } + #[cfg(feature = "sqlx-postgres")] assert_eq!( select .build(DbBackend::Postgres) @@ -533,20 +549,24 @@ mod tests { tea: None, }; let select = active_enum_child_model.find_related(ActiveEnum); - assert_eq!( - select.build(DbBackend::MySql).to_string(), - select.build(DbBackend::Sqlite).to_string(), - ); - assert_eq!( - select.build(DbBackend::MySql).to_string(), - [ - "SELECT `active_enum`.`id`, `active_enum`.`category`, `active_enum`.`color`, `active_enum`.`tea`", - "FROM `active_enum`", - "INNER JOIN `active_enum_child` ON `active_enum_child`.`parent_id` = `active_enum`.`id`", - "WHERE `active_enum_child`.`id` = 1", - ] - .join(" ") - ); + #[cfg(any(feature = "sqlx-mysql", feature = "sqlx-sqlite"))] + { + assert_eq!( + select.build(DbBackend::MySql).to_string(), + select.build(DbBackend::Sqlite).to_string(), + ); + assert_eq!( + select.build(DbBackend::MySql).to_string(), + [ + "SELECT `active_enum`.`id`, `active_enum`.`category`, `active_enum`.`color`, `active_enum`.`tea`", + "FROM `active_enum`", + "INNER JOIN `active_enum_child` ON `active_enum_child`.`parent_id` = `active_enum`.`id`", + "WHERE `active_enum_child`.`id` = 1", + ] + .join(" ") + ); + } + #[cfg(feature = "sqlx-postgres")] assert_eq!( select.build(DbBackend::Postgres).to_string(), [ @@ -559,22 +579,26 @@ mod tests { ); let select = ActiveEnumChild::find().find_also_related(ActiveEnum); - assert_eq!( - select.build(DbBackend::MySql).to_string(), - select.build(DbBackend::Sqlite).to_string(), - ); - assert_eq!( - select - .build(DbBackend::MySql) - .to_string(), - [ - "SELECT `active_enum_child`.`id` AS `A_id`, `active_enum_child`.`parent_id` AS `A_parent_id`, `active_enum_child`.`category` AS `A_category`, `active_enum_child`.`color` AS `A_color`, `active_enum_child`.`tea` AS `A_tea`,", - "`active_enum`.`id` AS `B_id`, `active_enum`.`category` AS `B_category`, `active_enum`.`color` AS `B_color`, `active_enum`.`tea` AS `B_tea`", - "FROM `active_enum_child`", - "LEFT JOIN `active_enum` ON `active_enum_child`.`parent_id` = `active_enum`.`id`", - ] - .join(" ") - ); + #[cfg(any(feature = "sqlx-mysql", feature = "sqlx-sqlite"))] + { + assert_eq!( + select.build(DbBackend::MySql).to_string(), + select.build(DbBackend::Sqlite).to_string(), + ); + assert_eq!( + select + .build(DbBackend::MySql) + .to_string(), + [ + "SELECT `active_enum_child`.`id` AS `A_id`, `active_enum_child`.`parent_id` AS `A_parent_id`, `active_enum_child`.`category` AS `A_category`, `active_enum_child`.`color` AS `A_color`, `active_enum_child`.`tea` AS `A_tea`,", + "`active_enum`.`id` AS `B_id`, `active_enum`.`category` AS `B_category`, `active_enum`.`color` AS `B_color`, `active_enum`.`tea` AS `B_tea`", + "FROM `active_enum_child`", + "LEFT JOIN `active_enum` ON `active_enum_child`.`parent_id` = `active_enum`.`id`", + ] + .join(" ") + ); + } + #[cfg(feature = "sqlx-postgres")] assert_eq!( select .build(DbBackend::Postgres) @@ -599,20 +623,24 @@ mod tests { tea: None, }; let select = active_enum_child_model.find_linked(active_enum_child::ActiveEnumLink); - assert_eq!( - select.build(DbBackend::MySql).to_string(), - select.build(DbBackend::Sqlite).to_string(), - ); - assert_eq!( - select.build(DbBackend::MySql).to_string(), - [ - "SELECT `active_enum`.`id`, `active_enum`.`category`, `active_enum`.`color`, `active_enum`.`tea`", - "FROM `active_enum`", - "INNER JOIN `active_enum_child` AS `r0` ON `r0`.`parent_id` = `active_enum`.`id`", - "WHERE `r0`.`id` = 1", - ] - .join(" ") - ); + #[cfg(any(feature = "sqlx-mysql", feature = "sqlx-sqlite"))] + { + assert_eq!( + select.build(DbBackend::MySql).to_string(), + select.build(DbBackend::Sqlite).to_string(), + ); + assert_eq!( + select.build(DbBackend::MySql).to_string(), + [ + "SELECT `active_enum`.`id`, `active_enum`.`category`, `active_enum`.`color`, `active_enum`.`tea`", + "FROM `active_enum`", + "INNER JOIN `active_enum_child` AS `r0` ON `r0`.`parent_id` = `active_enum`.`id`", + "WHERE `r0`.`id` = 1", + ] + .join(" ") + ); + } + #[cfg(feature = "sqlx-postgres")] assert_eq!( select.build(DbBackend::Postgres).to_string(), [ @@ -625,22 +653,26 @@ mod tests { ); let select = ActiveEnumChild::find().find_also_linked(active_enum_child::ActiveEnumLink); - assert_eq!( - select.build(DbBackend::MySql).to_string(), - select.build(DbBackend::Sqlite).to_string(), - ); - assert_eq!( - select - .build(DbBackend::MySql) - .to_string(), - [ - "SELECT `active_enum_child`.`id` AS `A_id`, `active_enum_child`.`parent_id` AS `A_parent_id`, `active_enum_child`.`category` AS `A_category`, `active_enum_child`.`color` AS `A_color`, `active_enum_child`.`tea` AS `A_tea`,", - "`r0`.`id` AS `B_id`, `r0`.`category` AS `B_category`, `r0`.`color` AS `B_color`, `r0`.`tea` AS `B_tea`", - "FROM `active_enum_child`", - "LEFT JOIN `active_enum` AS `r0` ON `active_enum_child`.`parent_id` = `r0`.`id`", - ] - .join(" ") - ); + #[cfg(any(feature = "sqlx-mysql", feature = "sqlx-sqlite"))] + { + assert_eq!( + select.build(DbBackend::MySql).to_string(), + select.build(DbBackend::Sqlite).to_string(), + ); + assert_eq!( + select + .build(DbBackend::MySql) + .to_string(), + [ + "SELECT `active_enum_child`.`id` AS `A_id`, `active_enum_child`.`parent_id` AS `A_parent_id`, `active_enum_child`.`category` AS `A_category`, `active_enum_child`.`color` AS `A_color`, `active_enum_child`.`tea` AS `A_tea`,", + "`r0`.`id` AS `B_id`, `r0`.`category` AS `B_category`, `r0`.`color` AS `B_color`, `r0`.`tea` AS `B_tea`", + "FROM `active_enum_child`", + "LEFT JOIN `active_enum` AS `r0` ON `active_enum_child`.`parent_id` = `r0`.`id`", + ] + .join(" ") + ); + } + #[cfg(feature = "sqlx-postgres")] assert_eq!( select .build(DbBackend::Postgres) diff --git a/tests/common/features/active_enum.rs b/tests/common/features/active_enum.rs index 01422973..1c043c3e 100644 --- a/tests/common/features/active_enum.rs +++ b/tests/common/features/active_enum.rs @@ -2,7 +2,8 @@ use super::sea_orm_active_enums::*; use sea_orm::entity::prelude::*; #[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(schema_name = "public", table_name = "active_enum")] +#[cfg_attr(feature = "sqlx-postgres", sea_orm(schema_name = "public"))] +#[sea_orm(table_name = "active_enum")] pub struct Model { #[sea_orm(primary_key)] pub id: i32, diff --git a/tests/common/features/active_enum_child.rs b/tests/common/features/active_enum_child.rs index 9c98b280..30564a4f 100644 --- a/tests/common/features/active_enum_child.rs +++ b/tests/common/features/active_enum_child.rs @@ -2,7 +2,8 @@ use super::sea_orm_active_enums::*; use sea_orm::entity::prelude::*; #[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(schema_name = "public", table_name = "active_enum_child")] +#[cfg_attr(feature = "sqlx-postgres", sea_orm(schema_name = "public"))] +#[sea_orm(table_name = "active_enum_child")] pub struct Model { #[sea_orm(primary_key)] pub id: i32, From 5bff85239e5be021d3024e58b56bb4461367c225 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Fri, 10 Dec 2021 17:10:44 +0800 Subject: [PATCH 20/36] Add docker create script for contributors to setup development environment locally --- build-tools/docker-compose.yml | 93 ++++++++++++++++++++++++++++++++++ build-tools/docker-create.sh | 87 +++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 build-tools/docker-compose.yml create mode 100644 build-tools/docker-create.sh diff --git a/build-tools/docker-compose.yml b/build-tools/docker-compose.yml new file mode 100644 index 00000000..71388959 --- /dev/null +++ b/build-tools/docker-compose.yml @@ -0,0 +1,93 @@ +version: "3" + +services: + # + # MariaDB + # + + mariadb_10_6: + image: mariadb:10.6 + ports: + - 3306 + environment: + MYSQL_DB: mysql + MYSQL_USER: sea + MYSQL_PASSWORD: sea + MYSQL_ALLOW_EMPTY_PASSWORD: yes + MYSQL_ROOT_PASSWORD: root + + mariadb_10_5: + image: mariadb:10.5 + ports: + - 3306 + environment: + MYSQL_DB: mysql + MYSQL_USER: sea + MYSQL_PASSWORD: sea + MYSQL_ALLOW_EMPTY_PASSWORD: yes + MYSQL_ROOT_PASSWORD: root + + mariadb_10_4: + image: mariadb:10.4 + ports: + - 3306 + environment: + MYSQL_DB: mysql + MYSQL_USER: sea + MYSQL_PASSWORD: sea + MYSQL_ALLOW_EMPTY_PASSWORD: yes + MYSQL_ROOT_PASSWORD: root + + # + # MySQL + # + + mysql_8_0: + image: mysql:8.0 + ports: + - 3306 + environment: + MYSQL_DB: mysql + MYSQL_USER: sea + MYSQL_PASSWORD: sea + MYSQL_ALLOW_EMPTY_PASSWORD: yes + MYSQL_ROOT_PASSWORD: root + + mysql_5_7: + image: mysql:5.7 + ports: + - 3306 + environment: + MYSQL_DB: mysql + MYSQL_USER: sea + MYSQL_PASSWORD: sea + MYSQL_ALLOW_EMPTY_PASSWORD: yes + MYSQL_ROOT_PASSWORD: root + + # + # PostgreSQL + # + + postgres_13: + image: postgres:13 + ports: + - 5432 + environment: + POSTGRES_USER: root + POSTGRES_PASSWORD: root + + postgres_12: + image: postgres:12 + ports: + - 5432 + environment: + POSTGRES_USER: root + POSTGRES_PASSWORD: root + + postgres_11: + image: postgres:11 + ports: + - 5432 + environment: + POSTGRES_USER: root + POSTGRES_PASSWORD: root diff --git a/build-tools/docker-create.sh b/build-tools/docker-create.sh new file mode 100644 index 00000000..cf5aac4e --- /dev/null +++ b/build-tools/docker-create.sh @@ -0,0 +1,87 @@ +# Some Common Docker Commands You Might Need (use with caution) +# +# Delete all containers +# $ docker rm -f $(docker ps -a -q) +# +# Delete all volumns +# $ docker volume rm $(docker volume ls -q) +# +# Delete all images +# $ docker image rm $(docker image ls -q) + +# Setup MariaDB + +docker run \ + --name "mariadb-10.6" \ + --env MYSQL_DB="mysql" \ + --env MYSQL_USER="sea" \ + --env MYSQL_PASSWORD="sea" \ + --env MYSQL_ALLOW_EMPTY_PASSWORD="yes" \ + --env MYSQL_ROOT_PASSWORD="root" \ + -d -p 3306:3306 mariadb:10.6 +docker stop "mariadb-10.6" + +docker run \ + --name "mariadb-10.5" \ + --env MYSQL_DB="mysql" \ + --env MYSQL_USER="sea" \ + --env MYSQL_PASSWORD="sea" \ + --env MYSQL_ALLOW_EMPTY_PASSWORD="yes" \ + --env MYSQL_ROOT_PASSWORD="root" \ + -d -p 3306:3306 mariadb:10.5 +docker stop "mariadb-10.5" + +docker run \ + --name "mariadb-10.4" \ + --env MYSQL_DB="mysql" \ + --env MYSQL_USER="sea" \ + --env MYSQL_PASSWORD="sea" \ + --env MYSQL_ALLOW_EMPTY_PASSWORD="yes" \ + --env MYSQL_ROOT_PASSWORD="root" \ + -d -p 3306:3306 mariadb:10.4 +docker stop "mariadb-10.4" + +# Setup MySQL + +docker run \ + --name "mysql-8.0" \ + --env MYSQL_DB="mysql" \ + --env MYSQL_USER="sea" \ + --env MYSQL_PASSWORD="sea" \ + --env MYSQL_ALLOW_EMPTY_PASSWORD="yes" \ + --env MYSQL_ROOT_PASSWORD="root" \ + -d -p 3306:3306 mysql:8.0 +docker stop "mysql-8.0" + +docker run \ + --name "mysql-5.7" \ + --env MYSQL_DB="mysql" \ + --env MYSQL_USER="sea" \ + --env MYSQL_PASSWORD="sea" \ + --env MYSQL_ALLOW_EMPTY_PASSWORD="yes" \ + --env MYSQL_ROOT_PASSWORD="root" \ + -d -p 3306:3306 mysql:5.7 +docker stop "mysql-5.7" + +# Setup PostgreSQL + +docker run \ + --name "postgres-13" \ + --env POSTGRES_USER="root" \ + --env POSTGRES_PASSWORD="root" \ + -d -p 5432:5432 postgres:13 +docker stop "postgres-13" + +docker run \ + --name "postgres-12" \ + --env POSTGRES_USER="root" \ + --env POSTGRES_PASSWORD="root" \ + -d -p 5432:5432 postgres:12 +docker stop "postgres-12" + +docker run \ + --name "postgres-11" \ + --env POSTGRES_USER="root" \ + --env POSTGRES_PASSWORD="root" \ + -d -p 5432:5432 postgres:11 +docker stop "postgres-11" From f5f6a6774f3088d764006a6681f8c8019730d0ac Mon Sep 17 00:00:00 2001 From: Billy Chan <30400950+billy1624@users.noreply.github.com> Date: Wed, 15 Dec 2021 00:52:50 +0800 Subject: [PATCH 21/36] Codegen ActiveEnum & Create Enum From ActiveEnum (#348) --- sea-orm-cli/Cargo.toml | 2 +- sea-orm-codegen/Cargo.toml | 2 +- sea-orm-codegen/src/entity/active_enum.rs | 31 ++++++++++ sea-orm-codegen/src/entity/column.rs | 35 +++++------ sea-orm-codegen/src/entity/mod.rs | 2 + sea-orm-codegen/src/entity/transformer.rs | 27 ++++++++- sea-orm-codegen/src/entity/writer.rs | 72 +++++++++++++++++++---- src/schema/entity.rs | 45 ++++++++++---- tests/active_enum_tests.rs | 4 +- 9 files changed, 176 insertions(+), 44 deletions(-) create mode 100644 sea-orm-codegen/src/entity/active_enum.rs diff --git a/sea-orm-cli/Cargo.toml b/sea-orm-cli/Cargo.toml index 6f67ccd6..0c8a0660 100644 --- a/sea-orm-cli/Cargo.toml +++ b/sea-orm-cli/Cargo.toml @@ -22,7 +22,7 @@ clap = { version = "^2.33.3" } dotenv = { version = "^0.15" } async-std = { version = "^1.9", features = [ "attributes" ] } sea-orm-codegen = { version = "^0.4.2", path = "../sea-orm-codegen" } -sea-schema = { version = "^0.2.9", default-features = false, features = [ +sea-schema = { version = "0.3.0", default-features = false, features = [ "debug-print", "sqlx-mysql", "sqlx-postgres", diff --git a/sea-orm-codegen/Cargo.toml b/sea-orm-codegen/Cargo.toml index a4b0a57b..2f2cfeaf 100644 --- a/sea-orm-codegen/Cargo.toml +++ b/sea-orm-codegen/Cargo.toml @@ -15,7 +15,7 @@ name = "sea_orm_codegen" path = "src/lib.rs" [dependencies] -sea-query = { version = "^0.16.4" } +sea-query = { version = "0.20.0" } syn = { version = "^1", default-features = false, features = [ "derive", "parsing", diff --git a/sea-orm-codegen/src/entity/active_enum.rs b/sea-orm-codegen/src/entity/active_enum.rs new file mode 100644 index 00000000..d92423f2 --- /dev/null +++ b/sea-orm-codegen/src/entity/active_enum.rs @@ -0,0 +1,31 @@ +use heck::CamelCase; +use proc_macro2::TokenStream; +use quote::{format_ident, quote}; + +#[derive(Clone, Debug)] +pub struct ActiveEnum { + pub(crate) enum_name: String, + pub(crate) values: Vec, +} + +impl ActiveEnum { + pub fn impl_active_enum(&self) -> TokenStream { + let enum_name = &self.enum_name; + let enum_iden = format_ident!("{}", enum_name.to_camel_case()); + let values = &self.values; + let variants = self + .values + .iter() + .map(|v| format_ident!("{}", v.to_camel_case())); + quote! { + #[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum)] + #[sea_orm(rs_type = "String", db_type = "Enum", enum_name = #enum_name)] + pub enum #enum_iden { + #( + #[sea_orm(string_value = #values)] + #variants, + )* + } + } + } +} diff --git a/sea-orm-codegen/src/entity/column.rs b/sea-orm-codegen/src/entity/column.rs index 39eb340c..35904600 100644 --- a/sea-orm-codegen/src/entity/column.rs +++ b/sea-orm-codegen/src/entity/column.rs @@ -24,26 +24,27 @@ impl Column { pub fn get_rs_type(&self) -> TokenStream { #[allow(unreachable_patterns)] - let ident: TokenStream = match self.col_type { + let ident: TokenStream = match &self.col_type { ColumnType::Char(_) | ColumnType::String(_) | ColumnType::Text - | ColumnType::Custom(_) => "String", - ColumnType::TinyInteger(_) => "i8", - ColumnType::SmallInteger(_) => "i16", - ColumnType::Integer(_) => "i32", - ColumnType::BigInteger(_) => "i64", - ColumnType::Float(_) => "f32", - ColumnType::Double(_) => "f64", - ColumnType::Json | ColumnType::JsonBinary => "Json", - ColumnType::Date => "Date", - ColumnType::Time(_) => "Time", - ColumnType::DateTime(_) | ColumnType::Timestamp(_) => "DateTime", - ColumnType::TimestampWithTimeZone(_) => "DateTimeWithTimeZone", - ColumnType::Decimal(_) | ColumnType::Money(_) => "Decimal", - ColumnType::Uuid => "Uuid", - ColumnType::Binary(_) => "Vec", - ColumnType::Boolean => "bool", + | ColumnType::Custom(_) => "String".to_owned(), + ColumnType::TinyInteger(_) => "i8".to_owned(), + ColumnType::SmallInteger(_) => "i16".to_owned(), + ColumnType::Integer(_) => "i32".to_owned(), + ColumnType::BigInteger(_) => "i64".to_owned(), + ColumnType::Float(_) => "f32".to_owned(), + ColumnType::Double(_) => "f64".to_owned(), + ColumnType::Json | ColumnType::JsonBinary => "Json".to_owned(), + ColumnType::Date => "Date".to_owned(), + ColumnType::Time(_) => "Time".to_owned(), + ColumnType::DateTime(_) | ColumnType::Timestamp(_) => "DateTime".to_owned(), + ColumnType::TimestampWithTimeZone(_) => "DateTimeWithTimeZone".to_owned(), + ColumnType::Decimal(_) | ColumnType::Money(_) => "Decimal".to_owned(), + ColumnType::Uuid => "Uuid".to_owned(), + ColumnType::Binary(_) => "Vec".to_owned(), + ColumnType::Boolean => "bool".to_owned(), + ColumnType::Enum(name, _) => name.to_camel_case(), _ => unimplemented!(), } .parse() diff --git a/sea-orm-codegen/src/entity/mod.rs b/sea-orm-codegen/src/entity/mod.rs index ee0ee830..cb461904 100644 --- a/sea-orm-codegen/src/entity/mod.rs +++ b/sea-orm-codegen/src/entity/mod.rs @@ -1,3 +1,4 @@ +mod active_enum; mod base_entity; mod column; mod conjunct_relation; @@ -6,6 +7,7 @@ mod relation; mod transformer; mod writer; +pub use active_enum::*; pub use base_entity::*; pub use column::*; pub use conjunct_relation::*; diff --git a/sea-orm-codegen/src/entity/transformer.rs b/sea-orm-codegen/src/entity/transformer.rs index 9a998b4b..8c9cdd1c 100644 --- a/sea-orm-codegen/src/entity/transformer.rs +++ b/sea-orm-codegen/src/entity/transformer.rs @@ -1,5 +1,6 @@ use crate::{ - Column, ConjunctRelation, Entity, EntityWriter, Error, PrimaryKey, Relation, RelationType, + ActiveEnum, Column, ConjunctRelation, Entity, EntityWriter, Error, PrimaryKey, Relation, + RelationType, }; use sea_query::TableStatement; use std::collections::HashMap; @@ -9,6 +10,7 @@ pub struct EntityTransformer; impl EntityTransformer { pub fn transform(table_stmts: Vec) -> Result { + let mut enums: HashMap = HashMap::new(); let mut inverse_relations: HashMap> = HashMap::new(); let mut conjunct_relations: HashMap> = HashMap::new(); let mut entities = HashMap::new(); @@ -22,7 +24,15 @@ impl EntityTransformer { } }; let table_name = match table_create.get_table_name() { - Some(s) => s, + Some(table_ref) => match table_ref { + sea_query::TableRef::Table(t) + | sea_query::TableRef::SchemaTable(_, t) + | sea_query::TableRef::DatabaseSchemaTable(_, _, t) + | sea_query::TableRef::TableAlias(t, _) + | sea_query::TableRef::SchemaTableAlias(_, t, _) + | sea_query::TableRef::DatabaseSchemaTableAlias(_, _, t, _) => t.to_string(), + _ => unimplemented!(), + }, None => { return Err(Error::TransformError( "Table name should not be empty".into(), @@ -44,6 +54,18 @@ impl EntityTransformer { > 0; col }) + .map(|col| { + if let sea_query::ColumnType::Enum(enum_name, values) = &col.col_type { + enums.insert( + enum_name.clone(), + ActiveEnum { + enum_name: enum_name.clone(), + values: values.clone(), + }, + ); + } + col + }) .collect(); let mut ref_table_counts: HashMap = HashMap::new(); let relations: Vec = table_create @@ -170,6 +192,7 @@ impl EntityTransformer { } Ok(EntityWriter { entities: entities.into_iter().map(|(_, v)| v).collect(), + enums, }) } } diff --git a/sea-orm-codegen/src/entity/writer.rs b/sea-orm-codegen/src/entity/writer.rs index a3648da6..dc45cab0 100644 --- a/sea-orm-codegen/src/entity/writer.rs +++ b/sea-orm-codegen/src/entity/writer.rs @@ -1,13 +1,14 @@ -use std::str::FromStr; - -use crate::Entity; +use crate::{ActiveEnum, Entity}; +use heck::CamelCase; use proc_macro2::TokenStream; -use quote::quote; +use quote::{format_ident, quote}; +use std::{collections::HashMap, str::FromStr}; use syn::{punctuated::Punctuated, token::Comma}; #[derive(Clone, Debug)] pub struct EntityWriter { pub(crate) entities: Vec, + pub(crate) enums: HashMap, } pub struct WriterOutput { @@ -83,6 +84,9 @@ impl EntityWriter { files.extend(self.write_entities(expanded_format, with_serde)); files.push(self.write_mod()); files.push(self.write_prelude()); + if !self.enums.is_empty() { + files.push(self.write_sea_orm_active_enums()); + } WriterOutput { files } } @@ -112,7 +116,7 @@ impl EntityWriter { let code_blocks: Vec = self .entities .iter() - .map(|entity| Self::gen_mod(entity)) + .map(Self::gen_mod) .collect(); Self::write( &mut lines, @@ -122,6 +126,14 @@ impl EntityWriter { ); lines.push("".to_owned()); Self::write(&mut lines, code_blocks); + if !self.enums.is_empty() { + Self::write( + &mut lines, + vec![quote! { + pub mod sea_orm_active_enums; + }], + ); + } OutputFile { name: "mod.rs".to_owned(), content: lines.join("\n"), @@ -134,7 +146,7 @@ impl EntityWriter { let code_blocks = self .entities .iter() - .map(|entity| Self::gen_prelude_use(entity)) + .map(Self::gen_prelude_use) .collect(); Self::write(&mut lines, code_blocks); OutputFile { @@ -143,6 +155,28 @@ impl EntityWriter { } } + pub fn write_sea_orm_active_enums(&self) -> OutputFile { + let mut lines = Vec::new(); + Self::write_doc_comment(&mut lines); + Self::write( + &mut lines, + vec![quote! { + use sea_orm::entity::prelude::*; + }], + ); + lines.push("".to_owned()); + let code_blocks = self + .enums + .iter() + .map(|(_, active_enum)| active_enum.impl_active_enum()) + .collect(); + Self::write(&mut lines, code_blocks); + OutputFile { + name: "sea_orm_active_enums.rs".to_owned(), + content: lines.join("\n"), + } + } + pub fn write(lines: &mut Vec, code_blocks: Vec) { lines.extend( code_blocks @@ -163,8 +197,10 @@ impl EntityWriter { } pub fn gen_expanded_code_blocks(entity: &Entity, with_serde: &WithSerde) -> Vec { + let mut imports = Self::gen_import(with_serde); + imports.extend(Self::gen_import_active_enum(entity)); let mut code_blocks = vec![ - Self::gen_import(with_serde), + imports, Self::gen_entity_struct(), Self::gen_impl_entity_name(entity), Self::gen_model_struct(entity, with_serde), @@ -182,10 +218,9 @@ impl EntityWriter { } pub fn gen_compact_code_blocks(entity: &Entity, with_serde: &WithSerde) -> Vec { - let mut code_blocks = vec![ - Self::gen_import(with_serde), - Self::gen_compact_model_struct(entity, with_serde), - ]; + let mut imports = Self::gen_import(with_serde); + imports.extend(Self::gen_import_active_enum(entity)); + let mut code_blocks = vec![imports, Self::gen_compact_model_struct(entity, with_serde)]; let relation_defs = if entity.get_relation_enum_name().is_empty() { vec![ Self::gen_relation_enum(entity), @@ -249,6 +284,21 @@ impl EntityWriter { } } + pub fn gen_import_active_enum(entity: &Entity) -> TokenStream { + entity + .columns + .iter() + .fold(TokenStream::new(), |mut ts, col| { + if let sea_query::ColumnType::Enum(enum_name, _) = &col.col_type { + let enum_name = format_ident!("{}", enum_name.to_camel_case()); + ts.extend(vec![quote! { + use super::sea_orm_active_enums::#enum_name; + }]); + } + ts + }) + } + pub fn gen_model_struct(entity: &Entity, with_serde: &WithSerde) -> TokenStream { let column_names_snake_case = entity.get_column_names_snake_case(); let column_rs_types = entity.get_column_rs_types(); diff --git a/src/schema/entity.rs b/src/schema/entity.rs index cc185e69..9c422ed3 100644 --- a/src/schema/entity.rs +++ b/src/schema/entity.rs @@ -1,6 +1,6 @@ use crate::{ - unpack_table_ref, ColumnTrait, ColumnType, DbBackend, EntityTrait, Identity, Iterable, - PrimaryKeyToColumn, PrimaryKeyTrait, RelationTrait, Schema, + unpack_table_ref, ActiveEnum, ColumnTrait, ColumnType, DbBackend, EntityTrait, Identity, + Iterable, PrimaryKeyToColumn, PrimaryKeyTrait, RelationTrait, Schema, }; use sea_query::{ extension::postgres::{Type, TypeCreateStatement}, @@ -8,6 +8,14 @@ use sea_query::{ }; impl Schema { + /// Creates Postgres enums from an ActiveEnum. See [TypeCreateStatement] for more details + pub fn create_enum_from_active_enum(&self) -> TypeCreateStatement + where + A: ActiveEnum, + { + create_enum_from_active_enum::(self.backend) + } + /// Creates Postgres enums from an Entity. See [TypeCreateStatement] for more details pub fn create_enum_from_entity(&self, entity: E) -> Vec where @@ -25,6 +33,30 @@ impl Schema { } } +pub(crate) fn create_enum_from_active_enum(backend: DbBackend) -> TypeCreateStatement +where + A: ActiveEnum, +{ + if matches!(backend, DbBackend::MySql | DbBackend::Sqlite) { + panic!("TypeCreateStatement is not supported in MySQL & SQLite"); + } + let col_def = A::db_type(); + let col_type = col_def.get_column_type(); + create_enum_from_column_type(col_type) +} + +pub(crate) fn create_enum_from_column_type(col_type: &ColumnType) -> TypeCreateStatement { + let (name, values) = match col_type { + ColumnType::Enum(s, v) => (s.as_str(), v), + _ => panic!("Should be ColumnType::Enum"), + }; + Type::create() + .as_enum(Alias::new(name)) + .values(values.iter().map(|val| Alias::new(val.as_str()))) + .to_owned() +} + +#[allow(clippy::needless_borrow)] pub(crate) fn create_enum_from_entity(_: E, backend: DbBackend) -> Vec where E: EntityTrait, @@ -39,14 +71,7 @@ where if !matches!(col_type, ColumnType::Enum(_, _)) { continue; } - let (name, values) = match col_type { - ColumnType::Enum(s, v) => (s.as_str(), v), - _ => unreachable!(), - }; - let stmt = Type::create() - .as_enum(Alias::new(name)) - .values(values.iter().map(|val| Alias::new(val.as_str()))) - .to_owned(); + let stmt = create_enum_from_column_type(&col_type); vec.push(stmt); } vec diff --git a/tests/active_enum_tests.rs b/tests/active_enum_tests.rs index cb8e0092..1e5aa18b 100644 --- a/tests/active_enum_tests.rs +++ b/tests/active_enum_tests.rs @@ -390,8 +390,8 @@ pub async fn find_linked_active_enum(db: &DatabaseConnection) -> Result<(), DbEr #[cfg(test)] mod tests { use super::*; - use pretty_assertions::assert_eq; - use sea_orm::{DbBackend, QueryTrait}; + pub use pretty_assertions::assert_eq; + pub use sea_orm::{DbBackend, QueryTrait}; #[test] fn active_enum_find_related() { From 951e678da5c09d4d8fe7a4ae9555d823fa6c2540 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8D=92=E9=87=8E=E7=84=A1=E7=87=88?= Date: Wed, 15 Dec 2021 02:50:27 +0800 Subject: [PATCH 22/36] refactor: update to Axum v0.4.2 Refs: https://github.com/tokio-rs/axum/blob/main/axum/CHANGELOG.md#042-06-december-2021 --- examples/axum_example/Cargo.toml | 14 +++++++------- examples/axum_example/src/main.rs | 7 +++---- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/examples/axum_example/Cargo.toml b/examples/axum_example/Cargo.toml index 1a3336e2..3b07ce6d 100644 --- a/examples/axum_example/Cargo.toml +++ b/examples/axum_example/Cargo.toml @@ -9,11 +9,11 @@ publish = false [workspace] [dependencies] -tokio = { version = "1.5", features = ["full"] } -axum = { version = "0.3.0" } -tower = "0.4.10" -tower-http = { version = "0.1", features = ["fs"] } -tower-cookies = { version = "0.3" } +tokio = { version = "1.14", features = ["full"] } +axum = { version = "0.4.2" } +tower = "0.4.11" +tower-http = { version = "0.2", features = ["fs"] } +tower-cookies = { version = "0.4" } anyhow = "1" dotenv = "0.15" env_logger = "0.9" @@ -23,11 +23,11 @@ tera = "1" [dependencies.sea-orm] path = "../../" # remove this line in your own project -version = "^0.4.0" +version = "^0.4.2" features = ["macros", "runtime-tokio-native-tls"] default-features = false [features] default = ["sqlx-postgres"] sqlx-mysql = ["sea-orm/sqlx-mysql"] -sqlx-postgres = ["sea-orm/sqlx-postgres"] \ No newline at end of file +sqlx-postgres = ["sea-orm/sqlx-postgres"] diff --git a/examples/axum_example/src/main.rs b/examples/axum_example/src/main.rs index 7b0b428e..5c48d9dc 100644 --- a/examples/axum_example/src/main.rs +++ b/examples/axum_example/src/main.rs @@ -3,11 +3,10 @@ mod post; mod setup; use axum::{ - error_handling::HandleErrorExt, extract::{Extension, Form, Path, Query}, http::StatusCode, response::Html, - routing::{get, post, service_method_routing}, + routing::{get, post, get_service}, AddExtensionLayer, Router, Server, }; use flash::{get_flash_cookie, post_response, PostResponse}; @@ -47,11 +46,11 @@ async fn main() -> anyhow::Result<()> { .route("/delete/:id", post(delete_post)) .nest( "/static", - service_method_routing::get(ServeDir::new(concat!( + get_service(ServeDir::new(concat!( env!("CARGO_MANIFEST_DIR"), "/static" ))) - .handle_error(|error: std::io::Error| { + .handle_error(|error: std::io::Error| async move { ( StatusCode::INTERNAL_SERVER_ERROR, format!("Unhandled internal error: {}", error), From edf26efd6a5a55d60eaa8c6c39e46ad76823c0e9 Mon Sep 17 00:00:00 2001 From: Gabriel-Paulucci Date: Tue, 14 Dec 2021 19:43:36 -0300 Subject: [PATCH 23/36] Fix rocket version --- sea-orm-rocket/codegen/Cargo.toml | 2 +- sea-orm-rocket/lib/Cargo.toml | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/sea-orm-rocket/codegen/Cargo.toml b/sea-orm-rocket/codegen/Cargo.toml index 5ab21dcc..11970f06 100644 --- a/sea-orm-rocket/codegen/Cargo.toml +++ b/sea-orm-rocket/codegen/Cargo.toml @@ -17,6 +17,6 @@ devise = "0.3" quote = "1" [dev-dependencies] -rocket = { git = "https://github.com/SergioBenitez/Rocket.git", default-features = false } +rocket = { version = "0.5.0-rc.1", default-features = false } trybuild = "1.0" version_check = "0.9" diff --git a/sea-orm-rocket/lib/Cargo.toml b/sea-orm-rocket/lib/Cargo.toml index f4ad1adf..7f3107ca 100644 --- a/sea-orm-rocket/lib/Cargo.toml +++ b/sea-orm-rocket/lib/Cargo.toml @@ -13,7 +13,6 @@ edition = "2021" all-features = true [dependencies.rocket] -git = "https://github.com/SergioBenitez/Rocket.git" version = "0.5.0-rc.1" default-features = false @@ -22,6 +21,6 @@ path = "../codegen" version = "0.1.0-rc" [dev-dependencies.rocket] -git = "https://github.com/SergioBenitez/Rocket.git" +version = "0.5.0-rc.1" default-features = false features = ["json"] From b2549576bc75922feb76867cfb22dcd1828fefa7 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Wed, 15 Dec 2021 12:25:12 +0800 Subject: [PATCH 24/36] Fix rocket_example --- examples/rocket_example/Cargo.toml | 4 ++-- examples/rocket_example/src/main.rs | 29 +++++++++++++++-------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/examples/rocket_example/Cargo.toml b/examples/rocket_example/Cargo.toml index 7269d3d8..ffbb6af2 100644 --- a/examples/rocket_example/Cargo.toml +++ b/examples/rocket_example/Cargo.toml @@ -12,10 +12,10 @@ async-stream = { version = "^0.3" } async-trait = { version = "0.1" } futures = { version = "^0.3" } futures-util = { version = "^0.3" } -rocket = { git = "https://github.com/SergioBenitez/Rocket.git", features = [ +rocket = { version = "0.5.0-rc.1", features = [ "json", ] } -rocket_dyn_templates = { git = "https://github.com/SergioBenitez/Rocket.git", features = [ +rocket_dyn_templates = { version = "0.1.0-rc.1", features = [ "tera", ] } serde_json = { version = "^1" } diff --git a/examples/rocket_example/src/main.rs b/examples/rocket_example/src/main.rs index e0b01bea..5ec1e52f 100644 --- a/examples/rocket_example/src/main.rs +++ b/examples/rocket_example/src/main.rs @@ -7,7 +7,8 @@ use rocket::fs::{relative, FileServer}; use rocket::request::FlashMessage; use rocket::response::{Flash, Redirect}; use rocket::{Build, Request, Rocket}; -use rocket_dyn_templates::{context, Template}; +use rocket_dyn_templates::Template; +use serde_json::json; use sea_orm::{entity::*, query::*}; use sea_orm_rocket::{Connection, Database}; @@ -107,13 +108,13 @@ async fn list( Template::render( "index", - context! { - page: page, - posts_per_page: posts_per_page, - num_pages: num_pages, - posts: posts, - flash: flash.map(FlashMessage::into_inner), - }, + json! ({ + "page": page, + "posts_per_page": posts_per_page, + "num_pages": num_pages, + "posts": posts, + "flash": flash.map(FlashMessage::into_inner), + }) ) } @@ -128,9 +129,9 @@ async fn edit(conn: Connection<'_, Db>, id: i32) -> Template { Template::render( "edit", - context! { - post: post, - }, + json! ({ + "post": post, + }) ) } @@ -157,9 +158,9 @@ async fn destroy(conn: Connection<'_, Db>) -> Result<(), rocket::response::Debug pub fn not_found(req: &Request<'_>) -> Template { Template::render( "error/404", - context! { - uri: req.uri() - }, + json! ({ + "uri": req.uri() + }) ) } From 4072e7428481c4f7d6decf7d8210d75522266721 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Fri, 17 Dec 2021 11:14:54 +0800 Subject: [PATCH 25/36] cargo fmt --- sea-orm-codegen/src/entity/writer.rs | 12 +-- src/database/db_connection.rs | 12 ++- src/database/mock.rs | 2 +- src/database/stream/query.rs | 144 ++++++++++++++++++--------- src/database/stream/transaction.rs | 9 +- src/database/transaction.rs | 21 ++-- src/driver/mock.rs | 2 +- src/driver/sqlx_mysql.rs | 16 ++- src/driver/sqlx_postgres.rs | 16 ++- src/driver/sqlx_sqlite.rs | 16 ++- src/lib.rs | 4 +- src/metric.rs | 54 +++++----- 12 files changed, 195 insertions(+), 113 deletions(-) diff --git a/sea-orm-codegen/src/entity/writer.rs b/sea-orm-codegen/src/entity/writer.rs index dc45cab0..60a01eeb 100644 --- a/sea-orm-codegen/src/entity/writer.rs +++ b/sea-orm-codegen/src/entity/writer.rs @@ -113,11 +113,7 @@ impl EntityWriter { pub fn write_mod(&self) -> OutputFile { let mut lines = Vec::new(); Self::write_doc_comment(&mut lines); - let code_blocks: Vec = self - .entities - .iter() - .map(Self::gen_mod) - .collect(); + let code_blocks: Vec = self.entities.iter().map(Self::gen_mod).collect(); Self::write( &mut lines, vec![quote! { @@ -143,11 +139,7 @@ impl EntityWriter { pub fn write_prelude(&self) -> OutputFile { let mut lines = Vec::new(); Self::write_doc_comment(&mut lines); - let code_blocks = self - .entities - .iter() - .map(Self::gen_prelude_use) - .collect(); + let code_blocks = self.entities.iter().map(Self::gen_prelude_use).collect(); Self::write(&mut lines, code_blocks); OutputFile { name: "prelude.rs".to_owned(), diff --git a/src/database/db_connection.rs b/src/database/db_connection.rs index 24b30e9c..f4f91bcf 100644 --- a/src/database/db_connection.rs +++ b/src/database/db_connection.rs @@ -3,8 +3,8 @@ use crate::{ StatementBuilder, TransactionError, }; use sea_query::{MysqlQueryBuilder, PostgresQueryBuilder, QueryBuilder, SqliteQueryBuilder}; -use tracing::instrument; use std::{future::Future, pin::Pin}; +use tracing::instrument; use url::Url; #[cfg(feature = "sqlx-dep")] @@ -255,10 +255,14 @@ impl DatabaseConnection { #[cfg(feature = "sqlx-mysql")] DatabaseConnection::SqlxMySqlPoolConnection(conn) => conn.set_metric_callback(callback), #[cfg(feature = "sqlx-postgres")] - DatabaseConnection::SqlxPostgresPoolConnection(conn) => conn.set_metric_callback(callback), + DatabaseConnection::SqlxPostgresPoolConnection(conn) => { + conn.set_metric_callback(callback) + } #[cfg(feature = "sqlx-sqlite")] - DatabaseConnection::SqlxSqlitePoolConnection(conn) => conn.set_metric_callback(callback), - _ => {}, + DatabaseConnection::SqlxSqlitePoolConnection(conn) => { + conn.set_metric_callback(callback) + } + _ => {} } } } diff --git a/src/database/mock.rs b/src/database/mock.rs index b3ae74fc..844fcbd9 100644 --- a/src/database/mock.rs +++ b/src/database/mock.rs @@ -4,8 +4,8 @@ use crate::{ Statement, }; use sea_query::{Value, ValueType, Values}; -use tracing::instrument; use std::{collections::BTreeMap, sync::Arc}; +use tracing::instrument; /// Defines a Mock database suitable for testing #[derive(Debug)] diff --git a/src/database/stream/query.rs b/src/database/stream/query.rs index f967268b..232d69fe 100644 --- a/src/database/stream/query.rs +++ b/src/database/stream/query.rs @@ -28,29 +28,77 @@ pub struct QueryStream { } #[cfg(feature = "sqlx-mysql")] -impl From<(PoolConnection, Statement, Option)> for QueryStream { - fn from((conn, stmt, metric_callback): (PoolConnection, Statement, Option)) -> Self { +impl + From<( + PoolConnection, + Statement, + Option, + )> for QueryStream +{ + fn from( + (conn, stmt, metric_callback): ( + PoolConnection, + Statement, + Option, + ), + ) -> Self { QueryStream::build(stmt, InnerConnection::MySql(conn), metric_callback) } } #[cfg(feature = "sqlx-postgres")] -impl From<(PoolConnection, Statement, Option)> for QueryStream { - fn from((conn, stmt, metric_callback): (PoolConnection, Statement, Option)) -> Self { +impl + From<( + PoolConnection, + Statement, + Option, + )> for QueryStream +{ + fn from( + (conn, stmt, metric_callback): ( + PoolConnection, + Statement, + Option, + ), + ) -> Self { QueryStream::build(stmt, InnerConnection::Postgres(conn), metric_callback) } } #[cfg(feature = "sqlx-sqlite")] -impl From<(PoolConnection, Statement, Option)> for QueryStream { - fn from((conn, stmt, metric_callback): (PoolConnection, Statement, Option)) -> Self { +impl + From<( + PoolConnection, + Statement, + Option, + )> for QueryStream +{ + fn from( + (conn, stmt, metric_callback): ( + PoolConnection, + Statement, + Option, + ), + ) -> Self { QueryStream::build(stmt, InnerConnection::Sqlite(conn), metric_callback) } } #[cfg(feature = "mock")] -impl From<(Arc, Statement, Option)> for QueryStream { - fn from((conn, stmt, metric_callback): (Arc, Statement, Option)) -> Self { +impl + From<( + Arc, + Statement, + Option, + )> for QueryStream +{ + fn from( + (conn, stmt, metric_callback): ( + Arc, + Statement, + Option, + ), + ) -> Self { QueryStream::build(stmt, InnerConnection::Mock(conn), metric_callback) } } @@ -63,50 +111,52 @@ impl std::fmt::Debug for QueryStream { impl QueryStream { #[instrument(level = "trace", skip(metric_callback))] - fn build(stmt: Statement, conn: InnerConnection, metric_callback: Option) -> QueryStream { + fn build( + stmt: Statement, + conn: InnerConnection, + metric_callback: Option, + ) -> QueryStream { QueryStreamBuilder { stmt, conn, metric_callback, - stream_builder: |conn, stmt, metric_callback| { - match conn { - #[cfg(feature = "sqlx-mysql")] - InnerConnection::MySql(c) => { - let query = crate::driver::sqlx_mysql::sqlx_query(stmt); - crate::metric::metric_ok!(metric_callback, stmt, { - Box::pin( - c.fetch(query) - .map_ok(Into::into) - .map_err(crate::sqlx_error_to_query_err), - ) - }) - } - #[cfg(feature = "sqlx-postgres")] - InnerConnection::Postgres(c) => { - let query = crate::driver::sqlx_postgres::sqlx_query(stmt); - crate::metric::metric_ok!(metric_callback, stmt, { - Box::pin( - c.fetch(query) - .map_ok(Into::into) - .map_err(crate::sqlx_error_to_query_err), - ) - }) - } - #[cfg(feature = "sqlx-sqlite")] - InnerConnection::Sqlite(c) => { - let query = crate::driver::sqlx_sqlite::sqlx_query(stmt); - crate::metric::metric_ok!(metric_callback, stmt, { - Box::pin( - c.fetch(query) - .map_ok(Into::into) - .map_err(crate::sqlx_error_to_query_err), - ) - }) - } - #[cfg(feature = "mock")] - InnerConnection::Mock(c) => c.fetch(stmt), + stream_builder: |conn, stmt, metric_callback| match conn { + #[cfg(feature = "sqlx-mysql")] + InnerConnection::MySql(c) => { + let query = crate::driver::sqlx_mysql::sqlx_query(stmt); + crate::metric::metric_ok!(metric_callback, stmt, { + Box::pin( + c.fetch(query) + .map_ok(Into::into) + .map_err(crate::sqlx_error_to_query_err), + ) + }) } - } + #[cfg(feature = "sqlx-postgres")] + InnerConnection::Postgres(c) => { + let query = crate::driver::sqlx_postgres::sqlx_query(stmt); + crate::metric::metric_ok!(metric_callback, stmt, { + Box::pin( + c.fetch(query) + .map_ok(Into::into) + .map_err(crate::sqlx_error_to_query_err), + ) + }) + } + #[cfg(feature = "sqlx-sqlite")] + InnerConnection::Sqlite(c) => { + let query = crate::driver::sqlx_sqlite::sqlx_query(stmt); + crate::metric::metric_ok!(metric_callback, stmt, { + Box::pin( + c.fetch(query) + .map_ok(Into::into) + .map_err(crate::sqlx_error_to_query_err), + ) + }) + } + #[cfg(feature = "mock")] + InnerConnection::Mock(c) => c.fetch(stmt), + }, } .build() } diff --git a/src/database/stream/transaction.rs b/src/database/stream/transaction.rs index 1995e0b4..01b462d3 100644 --- a/src/database/stream/transaction.rs +++ b/src/database/stream/transaction.rs @@ -55,7 +55,8 @@ impl<'a> TransactionStream<'a> { c.fetch(query) .map_ok(Into::into) .map_err(crate::sqlx_error_to_query_err), - ) as Pin>>> + ) + as Pin>>> }) } #[cfg(feature = "sqlx-postgres")] @@ -66,7 +67,8 @@ impl<'a> TransactionStream<'a> { c.fetch(query) .map_ok(Into::into) .map_err(crate::sqlx_error_to_query_err), - ) as Pin>>> + ) + as Pin>>> }) } #[cfg(feature = "sqlx-sqlite")] @@ -77,7 +79,8 @@ impl<'a> TransactionStream<'a> { c.fetch(query) .map_ok(Into::into) .map_err(crate::sqlx_error_to_query_err), - ) as Pin>>> + ) + as Pin>>> }) } #[cfg(feature = "mock")] diff --git a/src/database/transaction.rs b/src/database/transaction.rs index 790483b4..e1f85536 100644 --- a/src/database/transaction.rs +++ b/src/database/transaction.rs @@ -7,8 +7,8 @@ use crate::{sqlx_error_to_exec_err, sqlx_error_to_query_err}; use futures::lock::Mutex; #[cfg(feature = "sqlx-dep")] use sqlx::{pool::PoolConnection, TransactionManager}; -use tracing::instrument; use std::{future::Future, pin::Pin, sync::Arc}; +use tracing::instrument; // 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 @@ -76,7 +76,8 @@ impl DatabaseTransaction { Arc::new(Mutex::new(InnerConnection::Mock(inner))), backend, metric_callback, - ).await + ) + .await } #[instrument(level = "trace", skip(metric_callback))] @@ -354,9 +355,14 @@ impl<'a> ConnectionTrait<'a> for DatabaseTransaction { &'a self, stmt: Statement, ) -> Pin> + 'a>> { - Box::pin( - async move { Ok(crate::TransactionStream::build(self.conn.lock().await, stmt, self.metric_callback.clone()).await) }, - ) + Box::pin(async move { + Ok(crate::TransactionStream::build( + self.conn.lock().await, + stmt, + self.metric_callback.clone(), + ) + .await) + }) } #[instrument(level = "trace")] @@ -364,8 +370,9 @@ impl<'a> ConnectionTrait<'a> for DatabaseTransaction { DatabaseTransaction::begin( Arc::clone(&self.conn), self.backend, - self.metric_callback.clone() - ).await + self.metric_callback.clone(), + ) + .await } /// Execute the function inside a transaction. diff --git a/src/driver/mock.rs b/src/driver/mock.rs index 12f3cc5c..cfdd22c5 100644 --- a/src/driver/mock.rs +++ b/src/driver/mock.rs @@ -3,7 +3,6 @@ use crate::{ Statement, Transaction, }; use futures::Stream; -use tracing::instrument; use std::{ fmt::Debug, pin::Pin, @@ -12,6 +11,7 @@ use std::{ Arc, Mutex, }, }; +use tracing::instrument; /// Defines a database driver for the [MockDatabase] #[derive(Debug)] diff --git a/src/driver/sqlx_mysql.rs b/src/driver/sqlx_mysql.rs index e818a6c4..5a3c0562 100644 --- a/src/driver/sqlx_mysql.rs +++ b/src/driver/sqlx_mysql.rs @@ -52,7 +52,10 @@ impl SqlxMySqlConnector { } match options.pool_options().connect_with(opt).await { Ok(pool) => Ok(DatabaseConnection::SqlxMySqlPoolConnection( - SqlxMySqlPoolConnection { pool, metric_callback: None }, + SqlxMySqlPoolConnection { + pool, + metric_callback: None, + }, )), Err(e) => Err(sqlx_error_to_conn_err(e)), } @@ -62,7 +65,10 @@ 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, metric_callback: None }) + DatabaseConnection::SqlxMySqlPoolConnection(SqlxMySqlPoolConnection { + pool, + metric_callback: None, + }) } } @@ -136,7 +142,11 @@ impl SqlxMySqlPoolConnection { debug_print!("{}", stmt); if let Ok(conn) = self.pool.acquire().await { - Ok(QueryStream::from((conn, stmt, self.metric_callback.clone()))) + Ok(QueryStream::from(( + conn, + stmt, + self.metric_callback.clone(), + ))) } else { Err(DbErr::Query( "Failed to acquire connection from pool.".to_owned(), diff --git a/src/driver/sqlx_postgres.rs b/src/driver/sqlx_postgres.rs index bf72f0de..f09c8760 100644 --- a/src/driver/sqlx_postgres.rs +++ b/src/driver/sqlx_postgres.rs @@ -52,7 +52,10 @@ impl SqlxPostgresConnector { } match options.pool_options().connect_with(opt).await { Ok(pool) => Ok(DatabaseConnection::SqlxPostgresPoolConnection( - SqlxPostgresPoolConnection { pool, metric_callback: None }, + SqlxPostgresPoolConnection { + pool, + metric_callback: None, + }, )), Err(e) => Err(sqlx_error_to_conn_err(e)), } @@ -62,7 +65,10 @@ 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, metric_callback: None }) + DatabaseConnection::SqlxPostgresPoolConnection(SqlxPostgresPoolConnection { + pool, + metric_callback: None, + }) } } @@ -136,7 +142,11 @@ impl SqlxPostgresPoolConnection { debug_print!("{}", stmt); if let Ok(conn) = self.pool.acquire().await { - Ok(QueryStream::from((conn, stmt, self.metric_callback.clone()))) + Ok(QueryStream::from(( + conn, + stmt, + self.metric_callback.clone(), + ))) } else { Err(DbErr::Query( "Failed to acquire connection from pool.".to_owned(), diff --git a/src/driver/sqlx_sqlite.rs b/src/driver/sqlx_sqlite.rs index d3498dc1..9940b7fa 100644 --- a/src/driver/sqlx_sqlite.rs +++ b/src/driver/sqlx_sqlite.rs @@ -56,7 +56,10 @@ impl SqlxSqliteConnector { } match options.pool_options().connect_with(opt).await { Ok(pool) => Ok(DatabaseConnection::SqlxSqlitePoolConnection( - SqlxSqlitePoolConnection { pool, metric_callback: None }, + SqlxSqlitePoolConnection { + pool, + metric_callback: None, + }, )), Err(e) => Err(sqlx_error_to_conn_err(e)), } @@ -66,7 +69,10 @@ 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, metric_callback: None }) + DatabaseConnection::SqlxSqlitePoolConnection(SqlxSqlitePoolConnection { + pool, + metric_callback: None, + }) } } @@ -140,7 +146,11 @@ impl SqlxSqlitePoolConnection { debug_print!("{}", stmt); if let Ok(conn) = self.pool.acquire().await { - Ok(QueryStream::from((conn, stmt, self.metric_callback.clone()))) + Ok(QueryStream::from(( + conn, + stmt, + self.metric_callback.clone(), + ))) } else { Err(DbErr::Query( "Failed to acquire connection from pool.".to_owned(), diff --git a/src/lib.rs b/src/lib.rs index 5b6787dc..c31b80a0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -276,6 +276,8 @@ pub mod entity; pub mod error; /// This module performs execution of queries on a Model or ActiveModel mod executor; +/// Holds types and methods to perform metric collection +pub mod metric; /// Holds types and methods to perform queries pub mod query; /// Holds types that defines the schemas of an Entity @@ -284,8 +286,6 @@ pub mod schema; #[cfg(feature = "macros")] pub mod tests_cfg; mod util; -/// Holds types and methods to perform metric collection -pub mod metric; pub use database::*; pub use driver::*; diff --git a/src/metric.rs b/src/metric.rs index 7aa3a0a2..f90114b5 100644 --- a/src/metric.rs +++ b/src/metric.rs @@ -1,4 +1,4 @@ -use std::{time::Duration, sync::Arc}; +use std::{sync::Arc, time::Duration}; pub(crate) type Callback = Arc) + Send + Sync>; @@ -17,39 +17,35 @@ pub struct Info<'a> { mod inner { macro_rules! metric { - ($metric_callback:expr, $stmt:expr, $code:block) => { - { - let _start = std::time::SystemTime::now(); - let res = $code; - if let Some(callback) = $metric_callback.as_deref() { - let info = crate::metric::Info { - elapsed: _start.elapsed().unwrap_or_default(), - statement: $stmt, - failed: res.is_err(), - }; - callback(&info); - } - res + ($metric_callback:expr, $stmt:expr, $code:block) => {{ + let _start = std::time::SystemTime::now(); + let res = $code; + if let Some(callback) = $metric_callback.as_deref() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: $stmt, + failed: res.is_err(), + }; + callback(&info); } - }; + res + }}; } pub(crate) use metric; macro_rules! metric_ok { - ($metric_callback:expr, $stmt:expr, $code:block) => { - { - let _start = std::time::SystemTime::now(); - let res = $code; - if let Some(callback) = $metric_callback.as_deref() { - let info = crate::metric::Info { - elapsed: _start.elapsed().unwrap_or_default(), - statement: $stmt, - failed: false, - }; - callback(&info); - } - res + ($metric_callback:expr, $stmt:expr, $code:block) => {{ + let _start = std::time::SystemTime::now(); + let res = $code; + if let Some(callback) = $metric_callback.as_deref() { + let info = crate::metric::Info { + elapsed: _start.elapsed().unwrap_or_default(), + statement: $stmt, + failed: false, + }; + callback(&info); } - }; + res + }}; } pub(crate) use metric_ok; } From 006d35313be4e5209278ddd7c5170cb1b2cca9e9 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Fri, 17 Dec 2021 11:39:53 +0800 Subject: [PATCH 26/36] Fix clippy warnings --- src/database/db_connection.rs | 10 ++-- src/database/stream/query.rs | 8 +-- src/database/stream/transaction.rs | 8 +-- src/executor/select.rs | 1 + src/metric.rs | 3 ++ tests/active_enum_tests.rs | 80 +++++++++++++++--------------- tests/relational_tests.rs | 2 + 7 files changed, 60 insertions(+), 52 deletions(-) diff --git a/src/database/db_connection.rs b/src/database/db_connection.rs index f4f91bcf..90016737 100644 --- a/src/database/db_connection.rs +++ b/src/database/db_connection.rs @@ -247,20 +247,22 @@ impl DatabaseConnection { impl DatabaseConnection { /// Sets a callback to metric this connection - pub fn set_metric_callback(&mut self, callback: F) + pub fn set_metric_callback(&mut self, _callback: F) where F: Fn(&crate::metric::Info<'_>) + Send + Sync + 'static, { match self { #[cfg(feature = "sqlx-mysql")] - DatabaseConnection::SqlxMySqlPoolConnection(conn) => conn.set_metric_callback(callback), + DatabaseConnection::SqlxMySqlPoolConnection(conn) => { + conn.set_metric_callback(_callback) + } #[cfg(feature = "sqlx-postgres")] DatabaseConnection::SqlxPostgresPoolConnection(conn) => { - conn.set_metric_callback(callback) + conn.set_metric_callback(_callback) } #[cfg(feature = "sqlx-sqlite")] DatabaseConnection::SqlxSqlitePoolConnection(conn) => { - conn.set_metric_callback(callback) + conn.set_metric_callback(_callback) } _ => {} } diff --git a/src/database/stream/query.rs b/src/database/stream/query.rs index 232d69fe..98f1142a 100644 --- a/src/database/stream/query.rs +++ b/src/database/stream/query.rs @@ -120,11 +120,11 @@ impl QueryStream { stmt, conn, metric_callback, - stream_builder: |conn, stmt, metric_callback| match conn { + stream_builder: |conn, stmt, _metric_callback| match conn { #[cfg(feature = "sqlx-mysql")] InnerConnection::MySql(c) => { let query = crate::driver::sqlx_mysql::sqlx_query(stmt); - crate::metric::metric_ok!(metric_callback, stmt, { + crate::metric::metric_ok!(_metric_callback, stmt, { Box::pin( c.fetch(query) .map_ok(Into::into) @@ -135,7 +135,7 @@ impl QueryStream { #[cfg(feature = "sqlx-postgres")] InnerConnection::Postgres(c) => { let query = crate::driver::sqlx_postgres::sqlx_query(stmt); - crate::metric::metric_ok!(metric_callback, stmt, { + crate::metric::metric_ok!(_metric_callback, stmt, { Box::pin( c.fetch(query) .map_ok(Into::into) @@ -146,7 +146,7 @@ impl QueryStream { #[cfg(feature = "sqlx-sqlite")] InnerConnection::Sqlite(c) => { let query = crate::driver::sqlx_sqlite::sqlx_query(stmt); - crate::metric::metric_ok!(metric_callback, stmt, { + crate::metric::metric_ok!(_metric_callback, stmt, { Box::pin( c.fetch(query) .map_ok(Into::into) diff --git a/src/database/stream/transaction.rs b/src/database/stream/transaction.rs index 01b462d3..daa912ef 100644 --- a/src/database/stream/transaction.rs +++ b/src/database/stream/transaction.rs @@ -44,13 +44,13 @@ impl<'a> TransactionStream<'a> { stmt, conn, metric_callback, - stream_builder: |conn, stmt, metric_callback| { + stream_builder: |conn, stmt, _metric_callback| { Box::pin(async move { match conn.deref_mut() { #[cfg(feature = "sqlx-mysql")] InnerConnection::MySql(c) => { let query = crate::driver::sqlx_mysql::sqlx_query(stmt); - crate::metric::metric_ok!(metric_callback, stmt, { + crate::metric::metric_ok!(_metric_callback, stmt, { Box::pin( c.fetch(query) .map_ok(Into::into) @@ -62,7 +62,7 @@ impl<'a> TransactionStream<'a> { #[cfg(feature = "sqlx-postgres")] InnerConnection::Postgres(c) => { let query = crate::driver::sqlx_postgres::sqlx_query(stmt); - crate::metric::metric_ok!(metric_callback, stmt, { + crate::metric::metric_ok!(_metric_callback, stmt, { Box::pin( c.fetch(query) .map_ok(Into::into) @@ -74,7 +74,7 @@ impl<'a> TransactionStream<'a> { #[cfg(feature = "sqlx-sqlite")] InnerConnection::Sqlite(c) => { let query = crate::driver::sqlx_sqlite::sqlx_query(stmt); - crate::metric::metric_ok!(metric_callback, stmt, { + crate::metric::metric_ok!(_metric_callback, stmt, { Box::pin( c.fetch(query) .map_ok(Into::into) diff --git a/src/executor/select.rs b/src/executor/select.rs index 4c0d8ecf..8d1d1b47 100644 --- a/src/executor/select.rs +++ b/src/executor/select.rs @@ -28,6 +28,7 @@ where S: SelectorTrait, { stmt: Statement, + #[allow(dead_code)] selector: S, } diff --git a/src/metric.rs b/src/metric.rs index f90114b5..97da30a1 100644 --- a/src/metric.rs +++ b/src/metric.rs @@ -2,6 +2,7 @@ use std::{sync::Arc, time::Duration}; pub(crate) type Callback = Arc) + Send + Sync>; +#[allow(unused_imports)] pub(crate) use inner::{metric, metric_ok}; #[derive(Debug)] @@ -16,6 +17,7 @@ pub struct Info<'a> { } mod inner { + #[allow(unused_macros)] macro_rules! metric { ($metric_callback:expr, $stmt:expr, $code:block) => {{ let _start = std::time::SystemTime::now(); @@ -32,6 +34,7 @@ mod inner { }}; } pub(crate) use metric; + #[allow(unused_macros)] macro_rules! metric_ok { ($metric_callback:expr, $stmt:expr, $code:block) => {{ let _start = std::time::SystemTime::now(); diff --git a/tests/active_enum_tests.rs b/tests/active_enum_tests.rs index 1e5aa18b..814f7bc4 100644 --- a/tests/active_enum_tests.rs +++ b/tests/active_enum_tests.rs @@ -401,15 +401,15 @@ mod tests { color: None, tea: None, }; - let select = active_enum_model.find_related(ActiveEnumChild); + let _select = active_enum_model.find_related(ActiveEnumChild); #[cfg(any(feature = "sqlx-mysql", feature = "sqlx-sqlite"))] { assert_eq!( - select.build(DbBackend::MySql).to_string(), - select.build(DbBackend::Sqlite).to_string(), + _select.build(DbBackend::MySql).to_string(), + _select.build(DbBackend::Sqlite).to_string(), ); assert_eq!( - select.build(DbBackend::MySql).to_string(), + _select.build(DbBackend::MySql).to_string(), [ "SELECT `active_enum_child`.`id`, `active_enum_child`.`parent_id`, `active_enum_child`.`category`, `active_enum_child`.`color`, `active_enum_child`.`tea`", "FROM `active_enum_child`", @@ -421,7 +421,7 @@ mod tests { } #[cfg(feature = "sqlx-postgres")] assert_eq!( - select.build(DbBackend::Postgres).to_string(), + _select.build(DbBackend::Postgres).to_string(), [ r#"SELECT "active_enum_child"."id", "active_enum_child"."parent_id", "active_enum_child"."category", "active_enum_child"."color", CAST("active_enum_child"."tea" AS text)"#, r#"FROM "public"."active_enum_child""#, @@ -431,15 +431,15 @@ mod tests { .join(" ") ); - let select = ActiveEnum::find().find_also_related(ActiveEnumChild); + let _select = ActiveEnum::find().find_also_related(ActiveEnumChild); #[cfg(any(feature = "sqlx-mysql", feature = "sqlx-sqlite"))] { assert_eq!( - select.build(DbBackend::MySql).to_string(), - select.build(DbBackend::Sqlite).to_string(), + _select.build(DbBackend::MySql).to_string(), + _select.build(DbBackend::Sqlite).to_string(), ); assert_eq!( - select + _select .build(DbBackend::MySql) .to_string(), [ @@ -453,7 +453,7 @@ mod tests { } #[cfg(feature = "sqlx-postgres")] assert_eq!( - select + _select .build(DbBackend::Postgres) .to_string(), [ @@ -474,15 +474,15 @@ mod tests { color: None, tea: None, }; - let select = active_enum_model.find_linked(active_enum::ActiveEnumChildLink); + let _select = active_enum_model.find_linked(active_enum::ActiveEnumChildLink); #[cfg(any(feature = "sqlx-mysql", feature = "sqlx-sqlite"))] { assert_eq!( - select.build(DbBackend::MySql).to_string(), - select.build(DbBackend::Sqlite).to_string(), + _select.build(DbBackend::MySql).to_string(), + _select.build(DbBackend::Sqlite).to_string(), ); assert_eq!( - select.build(DbBackend::MySql).to_string(), + _select.build(DbBackend::MySql).to_string(), [ "SELECT `active_enum_child`.`id`, `active_enum_child`.`parent_id`, `active_enum_child`.`category`, `active_enum_child`.`color`, `active_enum_child`.`tea`", "FROM `active_enum_child`", @@ -494,7 +494,7 @@ mod tests { } #[cfg(feature = "sqlx-postgres")] assert_eq!( - select.build(DbBackend::Postgres).to_string(), + _select.build(DbBackend::Postgres).to_string(), [ r#"SELECT "active_enum_child"."id", "active_enum_child"."parent_id", "active_enum_child"."category", "active_enum_child"."color", CAST("active_enum_child"."tea" AS text)"#, r#"FROM "public"."active_enum_child""#, @@ -504,15 +504,15 @@ mod tests { .join(" ") ); - let select = ActiveEnum::find().find_also_linked(active_enum::ActiveEnumChildLink); + let _select = ActiveEnum::find().find_also_linked(active_enum::ActiveEnumChildLink); #[cfg(any(feature = "sqlx-mysql", feature = "sqlx-sqlite"))] { assert_eq!( - select.build(DbBackend::MySql).to_string(), - select.build(DbBackend::Sqlite).to_string(), + _select.build(DbBackend::MySql).to_string(), + _select.build(DbBackend::Sqlite).to_string(), ); assert_eq!( - select + _select .build(DbBackend::MySql) .to_string(), [ @@ -526,7 +526,7 @@ mod tests { } #[cfg(feature = "sqlx-postgres")] assert_eq!( - select + _select .build(DbBackend::Postgres) .to_string(), [ @@ -548,15 +548,15 @@ mod tests { color: None, tea: None, }; - let select = active_enum_child_model.find_related(ActiveEnum); + let _select = active_enum_child_model.find_related(ActiveEnum); #[cfg(any(feature = "sqlx-mysql", feature = "sqlx-sqlite"))] { assert_eq!( - select.build(DbBackend::MySql).to_string(), - select.build(DbBackend::Sqlite).to_string(), + _select.build(DbBackend::MySql).to_string(), + _select.build(DbBackend::Sqlite).to_string(), ); assert_eq!( - select.build(DbBackend::MySql).to_string(), + _select.build(DbBackend::MySql).to_string(), [ "SELECT `active_enum`.`id`, `active_enum`.`category`, `active_enum`.`color`, `active_enum`.`tea`", "FROM `active_enum`", @@ -568,7 +568,7 @@ mod tests { } #[cfg(feature = "sqlx-postgres")] assert_eq!( - select.build(DbBackend::Postgres).to_string(), + _select.build(DbBackend::Postgres).to_string(), [ r#"SELECT "active_enum"."id", "active_enum"."category", "active_enum"."color", CAST("active_enum"."tea" AS text)"#, r#"FROM "public"."active_enum""#, @@ -578,15 +578,15 @@ mod tests { .join(" ") ); - let select = ActiveEnumChild::find().find_also_related(ActiveEnum); + let _select = ActiveEnumChild::find().find_also_related(ActiveEnum); #[cfg(any(feature = "sqlx-mysql", feature = "sqlx-sqlite"))] { assert_eq!( - select.build(DbBackend::MySql).to_string(), - select.build(DbBackend::Sqlite).to_string(), + _select.build(DbBackend::MySql).to_string(), + _select.build(DbBackend::Sqlite).to_string(), ); assert_eq!( - select + _select .build(DbBackend::MySql) .to_string(), [ @@ -600,7 +600,7 @@ mod tests { } #[cfg(feature = "sqlx-postgres")] assert_eq!( - select + _select .build(DbBackend::Postgres) .to_string(), [ @@ -622,15 +622,15 @@ mod tests { color: None, tea: None, }; - let select = active_enum_child_model.find_linked(active_enum_child::ActiveEnumLink); + let _select = active_enum_child_model.find_linked(active_enum_child::ActiveEnumLink); #[cfg(any(feature = "sqlx-mysql", feature = "sqlx-sqlite"))] { assert_eq!( - select.build(DbBackend::MySql).to_string(), - select.build(DbBackend::Sqlite).to_string(), + _select.build(DbBackend::MySql).to_string(), + _select.build(DbBackend::Sqlite).to_string(), ); assert_eq!( - select.build(DbBackend::MySql).to_string(), + _select.build(DbBackend::MySql).to_string(), [ "SELECT `active_enum`.`id`, `active_enum`.`category`, `active_enum`.`color`, `active_enum`.`tea`", "FROM `active_enum`", @@ -642,7 +642,7 @@ mod tests { } #[cfg(feature = "sqlx-postgres")] assert_eq!( - select.build(DbBackend::Postgres).to_string(), + _select.build(DbBackend::Postgres).to_string(), [ r#"SELECT "active_enum"."id", "active_enum"."category", "active_enum"."color", CAST("active_enum"."tea" AS text)"#, r#"FROM "public"."active_enum""#, @@ -652,15 +652,15 @@ mod tests { .join(" ") ); - let select = ActiveEnumChild::find().find_also_linked(active_enum_child::ActiveEnumLink); + let _select = ActiveEnumChild::find().find_also_linked(active_enum_child::ActiveEnumLink); #[cfg(any(feature = "sqlx-mysql", feature = "sqlx-sqlite"))] { assert_eq!( - select.build(DbBackend::MySql).to_string(), - select.build(DbBackend::Sqlite).to_string(), + _select.build(DbBackend::MySql).to_string(), + _select.build(DbBackend::Sqlite).to_string(), ); assert_eq!( - select + _select .build(DbBackend::MySql) .to_string(), [ @@ -674,7 +674,7 @@ mod tests { } #[cfg(feature = "sqlx-postgres")] assert_eq!( - select + _select .build(DbBackend::Postgres) .to_string(), [ diff --git a/tests/relational_tests.rs b/tests/relational_tests.rs index ed5e92f5..6a4f839f 100644 --- a/tests/relational_tests.rs +++ b/tests/relational_tests.rs @@ -71,6 +71,7 @@ pub async fn left_join() { .await .unwrap() .unwrap(); + assert_eq!(result.name.as_str(), "Baker 1"); assert_eq!(result.bakery_name, Some("SeaSide Bakery".to_string())); let select = baker::Entity::find() @@ -340,6 +341,7 @@ pub async fn group_by() { .unwrap() .unwrap(); + assert_eq!(result.name.as_str(), "Kate"); assert_eq!(result.number_orders, Some(2)); assert_eq!( result.total_spent, From acf8eac4419ddef90028d8ae839388986940b08d Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Fri, 17 Dec 2021 12:52:33 +0800 Subject: [PATCH 27/36] Show tracing log only when test failed --- sea-orm-macros/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/sea-orm-macros/src/lib.rs b/sea-orm-macros/src/lib.rs index 7fc4b3d0..90cfee60 100644 --- a/sea-orm-macros/src/lib.rs +++ b/sea-orm-macros/src/lib.rs @@ -598,6 +598,7 @@ pub fn test(_: TokenStream, input: TokenStream) -> TokenStream { fn #name() #ret { let _ = ::tracing_subscriber::fmt() .with_max_level(::tracing::Level::DEBUG) + .with_test_writer() .try_init(); crate::block_on!(async { #body }) } From 5104cd357305e8aaa3e9a31ca10ec608b9297a16 Mon Sep 17 00:00:00 2001 From: Billy Chan <30400950+billy1624@users.noreply.github.com> Date: Sat, 18 Dec 2021 14:30:10 +0800 Subject: [PATCH 28/36] Insert & Update Return `Model` (#339) * Update insert & update API * Update test cases * Update README * Fix clippy warnings * Fixup * Fixup --- README.md | 4 +- examples/basic/src/operation.rs | 6 +-- src/entity/active_model.rs | 32 +++++++------- src/entity/base_entity.rs | 2 - src/executor/insert.rs | 10 ++--- src/executor/update.rs | 15 +++---- src/lib.rs | 4 +- tests/active_enum_tests.rs | 36 ++++++++-------- tests/basic.rs | 6 +-- tests/byte_primary_key_tests.rs | 10 ++++- tests/common/bakery_chain/cake.rs | 6 +-- tests/crud/deletes.rs | 12 +++++- tests/crud/updates.rs | 13 +++--- tests/query_tests.rs | 6 +-- tests/relational_tests.rs | 71 ++++++++++++------------------- tests/sequential_op_tests.rs | 23 +++++----- tests/stream_tests.rs | 4 +- tests/string_primary_key_tests.rs | 34 ++++++++++++--- tests/transaction_tests.rs | 4 +- tests/uuid_tests.rs | 7 ++- 20 files changed, 160 insertions(+), 145 deletions(-) diff --git a/README.md b/README.md index 61bba222..6e785e9c 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ let mut pear: fruit::ActiveModel = pear.unwrap().into(); pear.name = Set("Sweet pear".to_owned()); // update one -let pear: fruit::ActiveModel = pear.update(db).await?; +let pear: fruit::Model = pear.update(db).await?; // update many: UPDATE "fruit" SET "cake_id" = NULL WHERE "fruit"."name" LIKE '%Apple%' Fruit::update_many() @@ -142,7 +142,7 @@ let banana = fruit::ActiveModel { }; // create, because primary key `id` is `Unset` -let mut banana = banana.save(db).await?; +let mut banana = banana.save(db).await?.into_active_model(); banana.name = Set("Banana Mongo".to_owned()); diff --git a/examples/basic/src/operation.rs b/examples/basic/src/operation.rs index 49d23919..4b84da15 100644 --- a/examples/basic/src/operation.rs +++ b/examples/basic/src/operation.rs @@ -33,7 +33,7 @@ pub async fn insert_and_update(db: &DbConn) -> Result<(), DbErr> { let mut pear: fruit::ActiveModel = pear.unwrap().into(); pear.name = Set("Sweet pear".to_owned()); - let pear: fruit::ActiveModel = pear.update(db).await?; + let pear: fruit::Model = pear.update(db).await?; println!(); println!("Updated: {:?}\n", pear); @@ -46,14 +46,14 @@ pub async fn save_active_model(db: &DbConn) -> Result<(), DbErr> { name: Set("Banana".to_owned()), ..Default::default() }; - let mut banana = banana.save(db).await?; + let mut banana: fruit::ActiveModel = banana.save(db).await?.into_active_model(); println!(); println!("Inserted: {:?}\n", banana); banana.name = Set("Banana Mongo".to_owned()); - let banana = banana.save(db).await?; + let banana: fruit::ActiveModel = banana.save(db).await?.into_active_model(); println!(); println!("Updated: {:?}\n", banana); diff --git a/src/entity/active_model.rs b/src/entity/active_model.rs index 06e01fcb..ba02a914 100644 --- a/src/entity/active_model.rs +++ b/src/entity/active_model.rs @@ -172,7 +172,6 @@ pub trait ActiveModelTrait: Clone + Debug { /// id: 15, /// name: "Apple Pie".to_owned(), /// } - /// .into_active_model() /// ); /// /// assert_eq!( @@ -225,7 +224,6 @@ pub trait ActiveModelTrait: Clone + Debug { /// id: 15, /// name: "Apple Pie".to_owned(), /// } - /// .into_active_model() /// ); /// /// assert_eq!( @@ -247,17 +245,17 @@ pub trait ActiveModelTrait: Clone + Debug { /// # Ok(()) /// # } /// ``` - async fn insert<'a, C>(self, db: &'a C) -> Result + async fn insert<'a, C>(self, db: &'a C) -> Result<::Model, DbErr> where ::Model: IntoActiveModel, Self: ActiveModelBehavior + 'a, C: ConnectionTrait<'a>, { let am = ActiveModelBehavior::before_save(self, true)?; - let am = ::insert(am) + let model = ::insert(am) .exec_with_returning(db) .await?; - ActiveModelBehavior::after_save(am, true) + Self::after_save(model, true) } /// Perform the `UPDATE` operation on an ActiveModel @@ -296,7 +294,6 @@ pub trait ActiveModelTrait: Clone + Debug { /// name: "Orange".to_owned(), /// cake_id: None, /// } - /// .into_active_model() /// ); /// /// assert_eq!( @@ -351,7 +348,6 @@ pub trait ActiveModelTrait: Clone + Debug { /// name: "Orange".to_owned(), /// cake_id: None, /// } - /// .into_active_model() /// ); /// /// assert_eq!( @@ -371,26 +367,26 @@ pub trait ActiveModelTrait: Clone + Debug { /// # Ok(()) /// # } /// ``` - async fn update<'a, C>(self, db: &'a C) -> Result + async fn update<'a, C>(self, db: &'a C) -> Result<::Model, DbErr> where ::Model: IntoActiveModel, Self: ActiveModelBehavior + 'a, C: ConnectionTrait<'a>, { let am = ActiveModelBehavior::before_save(self, false)?; - let am = Self::Entity::update(am).exec(db).await?; - ActiveModelBehavior::after_save(am, false) + let model: ::Model = Self::Entity::update(am).exec(db).await?; + Self::after_save(model, false) } /// Insert the model if primary key is unset, update otherwise. /// Only works if the entity has auto increment primary key. - async fn save<'a, C>(self, db: &'a C) -> Result + async fn save<'a, C>(self, db: &'a C) -> Result<::Model, DbErr> where ::Model: IntoActiveModel, Self: ActiveModelBehavior + 'a, C: ConnectionTrait<'a>, { - let mut am = self; + let am = self; let mut is_update = true; for key in ::PrimaryKey::iter() { let col = key.into_column(); @@ -400,11 +396,10 @@ pub trait ActiveModelTrait: Clone + Debug { } } if !is_update { - am = am.insert(db).await?; + am.insert(db).await } else { - am = am.update(db).await?; + am.update(db).await } - Ok(am) } /// Delete an active model by its primary key @@ -503,8 +498,11 @@ pub trait ActiveModelBehavior: ActiveModelTrait { } /// Will be called after saving - fn after_save(self, insert: bool) -> Result { - Ok(self) + fn after_save( + model: ::Model, + insert: bool, + ) -> Result<::Model, DbErr> { + Ok(model) } /// Will be called before deleting diff --git a/src/entity/base_entity.rs b/src/entity/base_entity.rs index e6247d35..418b3130 100644 --- a/src/entity/base_entity.rs +++ b/src/entity/base_entity.rs @@ -505,7 +505,6 @@ pub trait EntityTrait: EntityName { /// name: "Orange".to_owned(), /// cake_id: None, /// } - /// .into_active_model(), /// ); /// /// assert_eq!( @@ -563,7 +562,6 @@ pub trait EntityTrait: EntityName { /// name: "Orange".to_owned(), /// cake_id: None, /// } - /// .into_active_model(), /// ); /// /// assert_eq!( diff --git a/src/executor/insert.rs b/src/executor/insert.rs index a6dbcbd5..1d9f7442 100644 --- a/src/executor/insert.rs +++ b/src/executor/insert.rs @@ -55,7 +55,7 @@ where pub fn exec_with_returning<'a, C>( self, db: &'a C, - ) -> impl Future> + '_ + ) -> impl Future::Model, DbErr>> + '_ where ::Model: IntoActiveModel, C: ConnectionTrait<'a>, @@ -92,13 +92,13 @@ where pub fn exec_with_returning<'a, C>( self, db: &'a C, - ) -> impl Future> + '_ + ) -> impl Future::Model, DbErr>> + '_ where ::Model: IntoActiveModel, C: ConnectionTrait<'a>, A: 'a, { - exec_insert_with_returning(self.primary_key, self.query, db) + exec_insert_with_returning::(self.primary_key, self.query, db) } } @@ -140,7 +140,7 @@ async fn exec_insert_with_returning<'a, A, C>( primary_key: Option, mut insert_statement: InsertStatement, db: &'a C, -) -> Result +) -> Result<::Model, DbErr> where ::Model: IntoActiveModel, C: ConnectionTrait<'a>, @@ -175,7 +175,7 @@ where } }; match found { - Some(model) => Ok(model.into_active_model()), + Some(model) => Ok(model), None => Err(DbErr::Exec("Failed to find inserted item".to_owned())), } } diff --git a/src/executor/update.rs b/src/executor/update.rs index 44db7a7d..eb997f13 100644 --- a/src/executor/update.rs +++ b/src/executor/update.rs @@ -1,6 +1,6 @@ use crate::{ - error::*, ActiveModelTrait, ColumnTrait, ConnectionTrait, EntityTrait, IntoActiveModel, - Iterable, SelectModel, SelectorRaw, Statement, UpdateMany, UpdateOne, + error::*, ActiveModelTrait, ColumnTrait, ConnectionTrait, EntityTrait, Iterable, SelectModel, + SelectorRaw, Statement, UpdateMany, UpdateOne, }; use sea_query::{Alias, Expr, FromValueTuple, Query, UpdateStatement}; use std::future::Future; @@ -24,9 +24,8 @@ where A: ActiveModelTrait, { /// Execute an update operation on an ActiveModel - pub async fn exec<'b, C>(self, db: &'b C) -> Result + pub async fn exec<'b, C>(self, db: &'b C) -> Result<::Model, DbErr> where - ::Model: IntoActiveModel, C: ConnectionTrait<'b>, { // so that self is dropped before entering await @@ -84,9 +83,8 @@ async fn exec_update_and_return_updated<'a, A, C>( mut query: UpdateStatement, model: A, db: &'a C, -) -> Result +) -> Result<::Model, DbErr> where - ::Model: IntoActiveModel, A: ActiveModelTrait, C: ConnectionTrait<'a>, { @@ -112,7 +110,7 @@ where .await?; // If we got `None` then we are updating a row that does not exist. match found { - Some(model) => Ok(model.into_active_model()), + Some(model) => Ok(model), None => Err(DbErr::RecordNotFound( "None of the database rows are affected".to_owned(), )), @@ -130,7 +128,7 @@ where .await?; // If we cannot select the updated row from db by the cached primary key match found { - Some(model) => Ok(model.into_active_model()), + Some(model) => Ok(model), None => Err(DbErr::Exec("Failed to find inserted item".to_owned())), } } @@ -196,7 +194,6 @@ mod tests { id: 1, name: "Cheese Cake".to_owned(), } - .into_active_model() ); let model = cake::Model { diff --git a/src/lib.rs b/src/lib.rs index c31b80a0..f5387aeb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -184,7 +184,7 @@ //! pear.name = Set("Sweet pear".to_owned()); //! //! // update one -//! let pear: fruit::ActiveModel = pear.update(db).await?; +//! let pear: fruit::Model = pear.update(db).await?; //! //! // update many: UPDATE "fruit" SET "cake_id" = NULL WHERE "fruit"."name" LIKE '%Apple%' //! Fruit::update_many() @@ -207,7 +207,7 @@ //! }; //! //! // create, because primary key `id` is `Unset` -//! let mut banana = banana.save(db).await?; +//! let mut banana = banana.save(db).await?.into_active_model(); //! //! banana.name = Set("Banana Mongo".to_owned()); //! diff --git a/tests/active_enum_tests.rs b/tests/active_enum_tests.rs index 814f7bc4..4904cb40 100644 --- a/tests/active_enum_tests.rs +++ b/tests/active_enum_tests.rs @@ -27,25 +27,25 @@ async fn main() -> Result<(), DbErr> { pub async fn insert_active_enum(db: &DatabaseConnection) -> Result<(), DbErr> { use active_enum::*; - let am = ActiveModel { - category: Set(None), - color: Set(None), - tea: Set(None), - ..Default::default() - } - .insert(db) - .await?; + let model = Model { + id: 1, + category: None, + color: None, + tea: None, + }; - let model = Entity::find().one(db).await?.unwrap(); assert_eq!( model, - Model { - id: 1, - category: None, - color: None, - tea: None, + ActiveModel { + category: Set(None), + color: Set(None), + tea: Set(None), + ..Default::default() } + .insert(db) + .await? ); + assert_eq!(model, Entity::find().one(db).await?.unwrap()); assert_eq!( model, Entity::find() @@ -58,11 +58,11 @@ pub async fn insert_active_enum(db: &DatabaseConnection) -> Result<(), DbErr> { .unwrap() ); - let am = ActiveModel { + let _ = ActiveModel { category: Set(Some(Category::Big)), color: Set(Some(Color::Black)), tea: Set(Some(Tea::EverydayTea)), - ..am + ..model.into_active_model() } .save(db) .await?; @@ -89,7 +89,7 @@ pub async fn insert_active_enum(db: &DatabaseConnection) -> Result<(), DbErr> { .unwrap() ); - let res = am.delete(db).await?; + let res = model.into_active_model().delete(db).await?; assert_eq!(res.rows_affected, 1); assert_eq!(Entity::find().one(db).await?, None); @@ -146,7 +146,7 @@ pub async fn insert_active_enum_child(db: &DatabaseConnection) -> Result<(), DbE category: Set(Some(Category::Big)), color: Set(Some(Color::Black)), tea: Set(Some(Tea::EverydayTea)), - ..am + ..am.into_active_model() } .save(db) .await?; diff --git a/tests/basic.rs b/tests/basic.rs index ef379779..96eed084 100644 --- a/tests/basic.rs +++ b/tests/basic.rs @@ -45,17 +45,17 @@ async fn crud_cake(db: &DbConn) -> Result<(), DbErr> { ..Default::default() }; - let mut apple = apple.save(db).await?; + let mut apple = apple.save(db).await?.into_active_model(); println!(); println!("Inserted: {:?}", apple); assert_eq!( + apple, cake::ActiveModel { id: Set(1), name: Set("Apple Pie".to_owned()), - }, - apple + } ); apple.name = Set("Lemon Tart".to_owned()); diff --git a/tests/byte_primary_key_tests.rs b/tests/byte_primary_key_tests.rs index 173efc93..2f66a13a 100644 --- a/tests/byte_primary_key_tests.rs +++ b/tests/byte_primary_key_tests.rs @@ -52,12 +52,18 @@ pub async fn create_and_update(db: &DatabaseConnection) -> Result<(), DbErr> { )) ); - let update_res = Entity::update(updated_active_model.clone()) + let update_res = Entity::update(updated_active_model) .filter(Column::Id.eq(vec![1, 2, 3])) .exec(db) .await?; - assert_eq!(update_res, updated_active_model); + assert_eq!( + update_res, + Model { + id: vec![1, 2, 3], + value: "First Row (Updated)".to_owned(), + } + ); assert_eq!( Entity::find() diff --git a/tests/common/bakery_chain/cake.rs b/tests/common/bakery_chain/cake.rs index 0ecaf5de..fe380d74 100644 --- a/tests/common/bakery_chain/cake.rs +++ b/tests/common/bakery_chain/cake.rs @@ -70,15 +70,15 @@ impl ActiveModelBehavior for ActiveModel { } } - fn after_save(self, insert: bool) -> Result { + fn after_save(model: Model, insert: bool) -> Result { use rust_decimal_macros::dec; - if self.price.as_ref() < &dec!(0) { + if model.price < dec!(0) { Err(DbErr::Custom(format!( "[after_save] Invalid Price, insert: {}", insert ))) } else { - Ok(self) + Ok(model) } } diff --git a/tests/crud/deletes.rs b/tests/crud/deletes.rs index 4c34d36b..01cfc7c2 100644 --- a/tests/crud/deletes.rs +++ b/tests/crud/deletes.rs @@ -29,7 +29,11 @@ pub async fn test_delete_cake(db: &DbConn) { let cakes = Cake::find().all(db).await.unwrap(); assert_eq!(cakes.len(), initial_cakes + 1); - let _result = cake.delete(db).await.expect("failed to delete cake"); + let _result = cake + .into_active_model() + .delete(db) + .await + .expect("failed to delete cake"); let cakes = Cake::find().all(db).await.unwrap(); assert_eq!(cakes.len(), initial_cakes); @@ -52,7 +56,11 @@ pub async fn test_delete_bakery(db: &DbConn) { initial_bakeries + 1 ); - let _result = bakery.delete(db).await.expect("failed to delete bakery"); + let _result = bakery + .into_active_model() + .delete(db) + .await + .expect("failed to delete bakery"); assert_eq!( Bakery::find().all(db).await.unwrap().len(), diff --git a/tests/crud/updates.rs b/tests/crud/updates.rs index 55af604e..b8ea6eb7 100644 --- a/tests/crud/updates.rs +++ b/tests/crud/updates.rs @@ -43,8 +43,7 @@ pub async fn test_update_cake(db: &DbConn) { cake_am.name = Set("Extra chocolate mud cake".to_owned()); cake_am.price = Set(dec!(20.00)); - let _cake_update_res: cake::ActiveModel = - cake_am.update(db).await.expect("could not update cake"); + let _cake_update_res: cake::Model = cake_am.update(db).await.expect("could not update cake"); let cake: Option = Cake::find_by_id(cake_insert_res.last_insert_id) .one(db) @@ -80,7 +79,7 @@ pub async fn test_update_bakery(db: &DbConn) { bakery_am.name = Set("SeaBreeze Bakery".to_owned()); bakery_am.profit_margin = Set(12.00); - let _bakery_update_res: bakery::ActiveModel = + let _bakery_update_res: bakery::Model = bakery_am.update(db).await.expect("could not update bakery"); let bakery: Option = Bakery::find_by_id(bakery_insert_res.last_insert_id) @@ -109,13 +108,13 @@ pub async fn test_update_deleted_customer(db: &DbConn) { init_n_customers + 1 ); - let customer_id = customer.id.clone(); + let customer_id = customer.id; - let _ = customer.delete(db).await; + let _ = customer.into_active_model().delete(db).await; assert_eq!(Customer::find().count(db).await.unwrap(), init_n_customers); let customer = customer::ActiveModel { - id: customer_id.clone(), + id: Set(customer_id), name: Set("John 2".to_owned()), ..Default::default() }; @@ -131,7 +130,7 @@ pub async fn test_update_deleted_customer(db: &DbConn) { assert_eq!(Customer::find().count(db).await.unwrap(), init_n_customers); - let customer: Option = Customer::find_by_id(customer_id.clone().unwrap()) + let customer: Option = Customer::find_by_id(customer_id) .one(db) .await .expect("could not find customer"); diff --git a/tests/query_tests.rs b/tests/query_tests.rs index 9d22c7b0..e8b3c0da 100644 --- a/tests/query_tests.rs +++ b/tests/query_tests.rs @@ -43,7 +43,7 @@ pub async fn find_one_with_result() { let result = Bakery::find().one(&ctx.db).await.unwrap().unwrap(); - assert_eq!(result.id, bakery.id.unwrap()); + assert_eq!(result.id, bakery.id); ctx.delete().await; } @@ -83,13 +83,13 @@ pub async fn find_by_id_with_result() { .await .expect("could not insert bakery"); - let result = Bakery::find_by_id(bakery.id.clone().unwrap()) + let result = Bakery::find_by_id(bakery.id.clone()) .one(&ctx.db) .await .unwrap() .unwrap(); - assert_eq!(result.id, bakery.id.unwrap()); + assert_eq!(result.id, bakery.id); ctx.delete().await; } diff --git a/tests/relational_tests.rs b/tests/relational_tests.rs index 6a4f839f..196bb93c 100644 --- a/tests/relational_tests.rs +++ b/tests/relational_tests.rs @@ -35,7 +35,7 @@ pub async fn left_join() { "home": "0395555555", "address": "12 Test St, Testville, Vic, Australia" })), - bakery_id: Set(Some(bakery.id.clone().unwrap())), + bakery_id: Set(Some(bakery.id.clone())), ..Default::default() } .save(&ctx.db) @@ -124,8 +124,8 @@ pub async fn right_join() { .expect("could not insert customer"); let _order = order::ActiveModel { - bakery_id: Set(bakery.id.clone().unwrap()), - customer_id: Set(customer_kate.id.clone().unwrap()), + bakery_id: Set(bakery.id.clone()), + customer_id: Set(customer_kate.id.clone()), total: Set(dec!(15.10)), placed_at: Set(Utc::now().naive_utc()), @@ -210,8 +210,8 @@ pub async fn inner_join() { .expect("could not insert customer"); let kate_order_1 = order::ActiveModel { - bakery_id: Set(bakery.id.clone().unwrap()), - customer_id: Set(customer_kate.id.clone().unwrap()), + bakery_id: Set(bakery.id.clone()), + customer_id: Set(customer_kate.id.clone()), total: Set(dec!(15.10)), placed_at: Set(Utc::now().naive_utc()), @@ -222,8 +222,8 @@ pub async fn inner_join() { .expect("could not insert order"); let kate_order_2 = order::ActiveModel { - bakery_id: Set(bakery.id.clone().unwrap()), - customer_id: Set(customer_kate.id.clone().unwrap()), + bakery_id: Set(bakery.id.clone()), + customer_id: Set(customer_kate.id.clone()), total: Set(dec!(100.00)), placed_at: Set(Utc::now().naive_utc()), @@ -254,12 +254,12 @@ pub async fn inner_join() { assert_eq!(results.len(), 2); assert!((&results) .into_iter() - .any(|result| result.name == customer_kate.name.clone().unwrap() - && result.order_total == Some(kate_order_1.total.clone().unwrap()))); + .any(|result| result.name == customer_kate.name.clone() + && result.order_total == Some(kate_order_1.total.clone()))); assert!((&results) .into_iter() - .any(|result| result.name == customer_kate.name.clone().unwrap() - && result.order_total == Some(kate_order_2.total.clone().unwrap()))); + .any(|result| result.name == customer_kate.name.clone() + && result.order_total == Some(kate_order_2.total.clone()))); ctx.delete().await; } @@ -292,8 +292,8 @@ pub async fn group_by() { .expect("could not insert customer"); let kate_order_1 = order::ActiveModel { - bakery_id: Set(bakery.id.clone().unwrap()), - customer_id: Set(customer_kate.id.clone().unwrap()), + bakery_id: Set(bakery.id.clone()), + customer_id: Set(customer_kate.id.clone()), total: Set(dec!(99.95)), placed_at: Set(Utc::now().naive_utc()), @@ -304,8 +304,8 @@ pub async fn group_by() { .expect("could not insert order"); let kate_order_2 = order::ActiveModel { - bakery_id: Set(bakery.id.clone().unwrap()), - customer_id: Set(customer_kate.id.clone().unwrap()), + bakery_id: Set(bakery.id.clone()), + customer_id: Set(customer_kate.id.clone()), total: Set(dec!(200.00)), placed_at: Set(Utc::now().naive_utc()), @@ -345,27 +345,15 @@ pub async fn group_by() { assert_eq!(result.number_orders, Some(2)); assert_eq!( result.total_spent, - Some(kate_order_1.total.clone().unwrap() + kate_order_2.total.clone().unwrap()) + Some(kate_order_1.total.clone() + kate_order_2.total.clone()) ); assert_eq!( result.min_spent, - Some( - kate_order_1 - .total - .clone() - .unwrap() - .min(kate_order_2.total.clone().unwrap()) - ) + Some(kate_order_1.total.clone().min(kate_order_2.total.clone())) ); assert_eq!( result.max_spent, - Some( - kate_order_1 - .total - .clone() - .unwrap() - .max(kate_order_2.total.clone().unwrap()) - ) + Some(kate_order_1.total.clone().max(kate_order_2.total.clone())) ); ctx.delete().await; } @@ -399,8 +387,8 @@ pub async fn having() { .expect("could not insert customer"); let kate_order_1 = order::ActiveModel { - bakery_id: Set(bakery.id.clone().unwrap()), - customer_id: Set(customer_kate.id.clone().unwrap()), + bakery_id: Set(bakery.id.clone()), + customer_id: Set(customer_kate.id.clone()), total: Set(dec!(100.00)), placed_at: Set(Utc::now().naive_utc()), @@ -411,8 +399,8 @@ pub async fn having() { .expect("could not insert order"); let _kate_order_2 = order::ActiveModel { - bakery_id: Set(bakery.id.clone().unwrap()), - customer_id: Set(customer_kate.id.clone().unwrap()), + bakery_id: Set(bakery.id.clone()), + customer_id: Set(customer_kate.id.clone()), total: Set(dec!(12.00)), placed_at: Set(Utc::now().naive_utc()), @@ -431,8 +419,8 @@ pub async fn having() { .expect("could not insert customer"); let _bob_order_1 = order::ActiveModel { - bakery_id: Set(bakery.id.clone().unwrap()), - customer_id: Set(customer_bob.id.clone().unwrap()), + bakery_id: Set(bakery.id.clone()), + customer_id: Set(customer_bob.id.clone()), total: Set(dec!(50.0)), placed_at: Set(Utc::now().naive_utc()), @@ -443,8 +431,8 @@ pub async fn having() { .expect("could not insert order"); let _bob_order_2 = order::ActiveModel { - bakery_id: Set(bakery.id.clone().unwrap()), - customer_id: Set(customer_bob.id.clone().unwrap()), + bakery_id: Set(bakery.id.clone()), + customer_id: Set(customer_bob.id.clone()), total: Set(dec!(50.0)), placed_at: Set(Utc::now().naive_utc()), @@ -474,11 +462,8 @@ pub async fn having() { .unwrap(); assert_eq!(results.len(), 1); - assert_eq!(results[0].name, customer_kate.name.clone().unwrap()); - assert_eq!( - results[0].order_total, - Some(kate_order_1.total.clone().unwrap()) - ); + assert_eq!(results[0].name, customer_kate.name.clone()); + assert_eq!(results[0].order_total, Some(kate_order_1.total.clone())); ctx.delete().await; } diff --git a/tests/sequential_op_tests.rs b/tests/sequential_op_tests.rs index 30d9b041..8c7120c0 100644 --- a/tests/sequential_op_tests.rs +++ b/tests/sequential_op_tests.rs @@ -42,7 +42,7 @@ async fn seed_data(db: &DatabaseConnection) { let baker_1 = baker::ActiveModel { name: Set("Baker 1".to_owned()), contact_details: Set(serde_json::json!({})), - bakery_id: Set(Some(bakery.id.clone().unwrap())), + bakery_id: Set(Some(bakery.id.clone())), ..Default::default() } .save(db) @@ -52,7 +52,7 @@ async fn seed_data(db: &DatabaseConnection) { let _baker_2 = baker::ActiveModel { name: Set("Baker 2".to_owned()), contact_details: Set(serde_json::json!({})), - bakery_id: Set(Some(bakery.id.clone().unwrap())), + bakery_id: Set(Some(bakery.id.clone())), ..Default::default() } .save(db) @@ -64,7 +64,7 @@ async fn seed_data(db: &DatabaseConnection) { price: Set(dec!(10.25)), gluten_free: Set(false), serial: Set(Uuid::new_v4()), - bakery_id: Set(Some(bakery.id.clone().unwrap())), + bakery_id: Set(Some(bakery.id.clone())), ..Default::default() }; @@ -75,7 +75,7 @@ async fn seed_data(db: &DatabaseConnection) { let cake_baker = cakes_bakers::ActiveModel { cake_id: Set(cake_insert_res.last_insert_id as i32), - baker_id: Set(baker_1.id.clone().unwrap()), + baker_id: Set(baker_1.id.clone()), ..Default::default() }; @@ -97,8 +97,8 @@ async fn seed_data(db: &DatabaseConnection) { .expect("could not insert customer"); let kate_order_1 = order::ActiveModel { - bakery_id: Set(bakery.id.clone().unwrap()), - customer_id: Set(customer_kate.id.clone().unwrap()), + bakery_id: Set(bakery.id.clone()), + customer_id: Set(customer_kate.id.clone()), total: Set(dec!(99.95)), placed_at: Set(Utc::now().naive_utc()), @@ -112,7 +112,7 @@ async fn seed_data(db: &DatabaseConnection) { cake_id: Set(cake_insert_res.last_insert_id as i32), price: Set(dec!(10.00)), quantity: Set(12), - order_id: Set(kate_order_1.id.clone().unwrap()), + order_id: Set(kate_order_1.id.clone()), ..Default::default() } .save(db) @@ -123,7 +123,7 @@ async fn seed_data(db: &DatabaseConnection) { cake_id: Set(cake_insert_res.last_insert_id as i32), price: Set(dec!(50.00)), quantity: Set(2), - order_id: Set(kate_order_1.id.clone().unwrap()), + order_id: Set(kate_order_1.id.clone()), ..Default::default() } .save(db) @@ -243,7 +243,7 @@ async fn create_order(db: &DatabaseConnection, cake: cake::Model) { let order = order::ActiveModel { bakery_id: Set(cake.bakery_id.unwrap()), - customer_id: Set(another_customer.id.clone().unwrap()), + customer_id: Set(another_customer.id.clone()), total: Set(dec!(200.00)), placed_at: Set(Utc::now().naive_utc()), @@ -257,7 +257,7 @@ async fn create_order(db: &DatabaseConnection, cake: cake::Model) { cake_id: Set(cake.id), price: Set(dec!(10.00)), quantity: Set(300), - order_id: Set(order.id.clone().unwrap()), + order_id: Set(order.id.clone()), ..Default::default() } .save(db) @@ -276,7 +276,8 @@ pub async fn test_delete_bakery(db: &DatabaseConnection) { } .save(db) .await - .expect("could not insert bakery"); + .expect("could not insert bakery") + .into_active_model(); assert_eq!( Bakery::find().all(db).await.unwrap().len(), diff --git a/tests/stream_tests.rs b/tests/stream_tests.rs index 37e6c21d..ba070541 100644 --- a/tests/stream_tests.rs +++ b/tests/stream_tests.rs @@ -24,14 +24,14 @@ pub async fn stream() -> Result<(), DbErr> { .save(&ctx.db) .await?; - let result = Bakery::find_by_id(bakery.id.clone().unwrap()) + let result = Bakery::find_by_id(bakery.id.clone()) .stream(&ctx.db) .await? .next() .await .unwrap()?; - assert_eq!(result.id, bakery.id.unwrap()); + assert_eq!(result.id, bakery.id); ctx.delete().await; diff --git a/tests/string_primary_key_tests.rs b/tests/string_primary_key_tests.rs index c2e8d2db..56496bdc 100644 --- a/tests/string_primary_key_tests.rs +++ b/tests/string_primary_key_tests.rs @@ -29,9 +29,17 @@ pub async fn insert_repository(db: &DatabaseConnection) -> Result<(), DbErr> { } .into_active_model(); - let result = repository.clone().insert(db).await?; + let result = repository.insert(db).await?; - assert_eq!(repository, result); + assert_eq!( + result, + repository::Model { + id: "unique-id-001".to_owned(), + owner: "GC".to_owned(), + name: "G.C.".to_owned(), + description: None, + } + ); Ok(()) } @@ -69,12 +77,20 @@ pub async fn create_and_update_repository(db: &DatabaseConnection) -> Result<(), )) ); - let update_res = Repository::update(updated_active_model.clone()) + let update_res = Repository::update(updated_active_model) .filter(repository::Column::Id.eq("unique-id-002".to_owned())) .exec(db) .await?; - assert_eq!(update_res, updated_active_model); + assert_eq!( + update_res, + repository::Model { + id: "unique-id-002".to_owned(), + owner: "GC".to_owned(), + name: "G.C.".to_owned(), + description: Some("description...".to_owned()), + } + ); let updated_active_model = repository::ActiveModel { description: Set(None), @@ -86,7 +102,15 @@ pub async fn create_and_update_repository(db: &DatabaseConnection) -> Result<(), .exec(db) .await?; - assert_eq!(update_res, updated_active_model); + assert_eq!( + update_res, + repository::Model { + id: "unique-id-002".to_owned(), + owner: "GC".to_owned(), + name: "G.C.".to_owned(), + description: None, + } + ); Ok(()) } diff --git a/tests/transaction_tests.rs b/tests/transaction_tests.rs index 7845843e..34b8df22 100644 --- a/tests/transaction_tests.rs +++ b/tests/transaction_tests.rs @@ -408,7 +408,7 @@ pub async fn transaction_with_active_model_behaviour() -> Result<(), DbErr> { assert_eq!(cake::Entity::find().all(&txn).await?.len(), 2); assert_eq!( - readonly_cake_1.delete(&txn).await.err(), + readonly_cake_1.into_active_model().delete(&txn).await.err(), Some(DbErr::Custom( "[before_delete] Cannot be deleted".to_owned() )) @@ -428,7 +428,7 @@ pub async fn transaction_with_active_model_behaviour() -> Result<(), DbErr> { assert_eq!(cake::Entity::find().all(&txn).await?.len(), 3); assert_eq!( - readonly_cake_2.delete(&txn).await.err(), + readonly_cake_2.into_active_model().delete(&txn).await.err(), Some(DbErr::Custom("[after_delete] Cannot be deleted".to_owned())) ); diff --git a/tests/uuid_tests.rs b/tests/uuid_tests.rs index cdda344b..1053bb55 100644 --- a/tests/uuid_tests.rs +++ b/tests/uuid_tests.rs @@ -28,12 +28,11 @@ pub async fn insert_metadata(db: &DatabaseConnection) -> Result<(), DbErr> { bytes: vec![1, 2, 3], date: Some(Date::from_ymd(2021, 9, 27)), time: Some(Time::from_hms(11, 32, 55)), - } - .into_active_model(); + }; - let result = metadata.clone().insert(db).await?; + let result = metadata.clone().into_active_model().insert(db).await?; - assert_eq!(metadata, result); + assert_eq!(result, metadata); Ok(()) } From adfb9ead54b7f4775a9249db20db476cd74f9a96 Mon Sep 17 00:00:00 2001 From: Billy Chan <30400950+billy1624@users.noreply.github.com> Date: Sun, 19 Dec 2021 02:22:30 +0800 Subject: [PATCH 29/36] Rework `ActiveValue` (#340) * WIP * Fixup * Fixup * Update docs & rename `unset` * Deprecate `Unset()` and reexport `ActiveValue::NotSet` * Docs Co-authored-by: Chris Tsang --- README.md | 4 +- examples/basic/src/operation.rs | 2 +- sea-orm-macros/src/derives/active_model.rs | 18 +- src/entity/active_model.rs | 219 +++++++++++---------- src/lib.rs | 4 +- src/query/insert.rs | 4 +- src/query/update.rs | 2 +- tests/basic.rs | 4 +- 8 files changed, 137 insertions(+), 120 deletions(-) diff --git a/README.md b/README.md index 6e785e9c..636fe594 100644 --- a/README.md +++ b/README.md @@ -136,12 +136,12 @@ Fruit::update_many() ### Save ```rust let banana = fruit::ActiveModel { - id: Unset(None), + id: NotSet, name: Set("Banana".to_owned()), ..Default::default() }; -// create, because primary key `id` is `Unset` +// create, because primary key `id` is `NotSet` let mut banana = banana.save(db).await?.into_active_model(); banana.name = Set("Banana Mongo".to_owned()); diff --git a/examples/basic/src/operation.rs b/examples/basic/src/operation.rs index 4b84da15..787cbc96 100644 --- a/examples/basic/src/operation.rs +++ b/examples/basic/src/operation.rs @@ -81,7 +81,7 @@ mod form { async fn save_custom_active_model(db: &DbConn) -> Result<(), DbErr> { let pineapple = form::ActiveModel { - id: Unset(None), + id: NotSet, name: Set("Pineapple".to_owned()), }; diff --git a/sea-orm-macros/src/derives/active_model.rs b/sea-orm-macros/src/derives/active_model.rs index d691a724..635897dc 100644 --- a/sea-orm-macros/src/derives/active_model.rs +++ b/sea-orm-macros/src/derives/active_model.rs @@ -80,7 +80,7 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result::Model> for ActiveModel { fn from(m: ::Model) -> Self { Self { - #(#field: sea_orm::unchanged_active_value_not_intended_for_public_use(m.#field)),* + #(#field: sea_orm::ActiveValue::unchanged(m.#field)),* } } } @@ -99,18 +99,18 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result::Column) -> sea_orm::ActiveValue { match c { #(::Column::#name => { - let mut value = sea_orm::ActiveValue::unset(); + let mut value = sea_orm::ActiveValue::not_set(); std::mem::swap(&mut value, &mut self.#field); value.into_wrapped_value() },)* - _ => sea_orm::ActiveValue::unset(), + _ => sea_orm::ActiveValue::not_set(), } } fn get(&self, c: ::Column) -> sea_orm::ActiveValue { match c { #(::Column::#name => self.#field.clone().into_wrapped_value(),)* - _ => sea_orm::ActiveValue::unset(), + _ => sea_orm::ActiveValue::not_set(), } } @@ -121,23 +121,23 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result::Column) { + fn not_set(&mut self, c: ::Column) { match c { - #(::Column::#name => self.#field = sea_orm::ActiveValue::unset(),)* + #(::Column::#name => self.#field = sea_orm::ActiveValue::not_set(),)* _ => {}, } } - fn is_unset(&self, c: ::Column) -> bool { + fn is_not_set(&self, c: ::Column) -> bool { match c { - #(::Column::#name => self.#field.is_unset(),)* + #(::Column::#name => self.#field.is_not_set(),)* _ => panic!("This ActiveModel does not have this field"), } } fn default() -> Self { Self { - #(#field: sea_orm::ActiveValue::unset()),* + #(#field: sea_orm::ActiveValue::not_set()),* } } } diff --git a/src/entity/active_model.rs b/src/entity/active_model.rs index ba02a914..d4f635c0 100644 --- a/src/entity/active_model.rs +++ b/src/entity/active_model.rs @@ -5,35 +5,47 @@ use async_trait::async_trait; use sea_query::{Nullable, ValueTuple}; use std::fmt::Debug; -/// Defines a value from an ActiveModel and its state. -/// The field `value` takes in an [Option] type where `Option::Some(V)` , with `V` holding -/// the value that operations like `UPDATE` are being performed on and -/// the `state` field is either `ActiveValueState::Set` or `ActiveValueState::Unchanged`. -/// [Option::None] in the `value` field indicates no value being performed by an operation -/// and that the `state` field of the [ActiveValue] is set to `ActiveValueState::Unset` . -/// #### Example snippet -/// ```no_run -/// // The code snipped below does an UPDATE operation on a [ActiveValue] -/// // yielding the the SQL statement ` r#"UPDATE "fruit" SET "name" = 'Orange' WHERE "fruit"."id" = 1"# ` +pub use ActiveValue::NotSet; + +/// Defines a stateful value used in ActiveModel. /// +/// There are three possible state represented by three enum variants. +/// - [ActiveValue::Set]: A [Value] was set +/// - [ActiveValue::Unchanged]: A [Value] remain unchanged +/// - [ActiveValue::NotSet]: A NULL value similar to [Option::None] +/// +/// The stateful value is useful when constructing UPDATE SQL statement, +/// see an example below. +/// +/// # Examples +/// +/// ``` /// use sea_orm::tests_cfg::{cake, fruit}; /// use sea_orm::{entity::*, query::*, DbBackend}; /// -/// Update::one(fruit::ActiveModel { -/// id: ActiveValue::set(1), -/// name: ActiveValue::set("Orange".to_owned()), -/// cake_id: ActiveValue::unset(), -/// }) -/// .build(DbBackend::Postgres) -/// .to_string(); +/// // The code snipped below does an UPDATE operation on a `ActiveValue` +/// assert_eq!( +/// Update::one(fruit::ActiveModel { +/// id: ActiveValue::set(1), +/// name: ActiveValue::set("Orange".to_owned()), +/// cake_id: ActiveValue::not_set(), +/// }) +/// .build(DbBackend::Postgres) +/// .to_string(), +/// r#"UPDATE "fruit" SET "name" = 'Orange' WHERE "fruit"."id" = 1"# +/// ); /// ``` -#[derive(Clone, Debug, Default)] -pub struct ActiveValue +#[derive(Clone, Debug)] +pub enum ActiveValue where V: Into, { - value: Option, - state: ActiveValueState, + /// A [Value] was set + Set(V), + /// A [Value] remain unchanged + Unchanged(V), + /// A NULL value similar to [Option::None] + NotSet, } /// Defines a set operation on an [ActiveValue] @@ -45,31 +57,22 @@ where ActiveValue::set(v) } -/// Defines an unset operation on an [ActiveValue] +/// Defines an not set operation on an [ActiveValue] +#[deprecated( + since = "0.5.0", + note = "Please use [`ActiveValue::NotSet`] or [`NotSet`]" +)] #[allow(non_snake_case)] pub fn Unset(_: Option) -> ActiveValue where V: Into, { - ActiveValue::unset() + ActiveValue::not_set() } -// Defines the state of an [ActiveValue] -#[derive(Clone, Debug)] -enum ActiveValueState { - Set, - Unchanged, - Unset, -} - -impl Default for ActiveValueState { - fn default() -> Self { - Self::Unset - } -} - -#[doc(hidden)] -pub fn unchanged_active_value_not_intended_for_public_use(value: V) -> ActiveValue +/// Defines an unchanged operation on an [ActiveValue] +#[allow(non_snake_case)] +pub fn Unchanged(value: V) -> ActiveValue where V: Into, { @@ -93,11 +96,11 @@ pub trait ActiveModelTrait: Clone + Debug { /// Set the Value into an ActiveModel fn set(&mut self, c: ::Column, v: Value); - /// Set the state of an [ActiveValue] to the Unset state - fn unset(&mut self, c: ::Column); + /// Set the state of an [ActiveValue] to the not set state + fn not_set(&mut self, c: ::Column); /// Check the state of a [ActiveValue] - fn is_unset(&self, c: ::Column) -> bool; + fn is_not_set(&self, c: ::Column) -> bool; /// The default implementation of the ActiveModel fn default() -> Self; @@ -378,7 +381,7 @@ pub trait ActiveModelTrait: Clone + Debug { Self::after_save(model, false) } - /// Insert the model if primary key is unset, update otherwise. + /// Insert the model if primary key is not_set, update otherwise. /// Only works if the entity has auto increment primary key. async fn save<'a, C>(self, db: &'a C) -> Result<::Model, DbErr> where @@ -390,7 +393,7 @@ pub trait ActiveModelTrait: Clone + Debug { let mut is_update = true; for key in ::PrimaryKey::iter() { let col = key.into_column(); - if am.is_unset(col) { + if am.is_not_set(col) { is_update = false; break; } @@ -555,7 +558,7 @@ macro_rules! impl_into_active_value { fn into_active_value(self) -> ActiveValue> { match self { Some(value) => Set(Some(value)), - None => Unset(None), + None => NotSet, } } } @@ -564,7 +567,7 @@ macro_rules! impl_into_active_value { fn into_active_value(self) -> ActiveValue> { match self { Some(value) => Set(value), - None => Unset(None), + None => NotSet, } } } @@ -613,74 +616,80 @@ impl_into_active_value!(crate::prelude::Decimal, Set); #[cfg_attr(docsrs, doc(cfg(feature = "with-uuid")))] impl_into_active_value!(crate::prelude::Uuid, Set); +impl Default for ActiveValue +where + V: Into, +{ + fn default() -> Self { + Self::NotSet + } +} + impl ActiveValue where V: Into, { - /// Set the value of an [ActiveValue] and also set its state to `ActiveValueState::Set` + /// Create an [ActiveValue::Set] pub fn set(value: V) -> Self { - Self { - value: Some(value), - state: ActiveValueState::Set, - } + Self::Set(value) } - /// Check if the state of an [ActiveValue] is `ActiveValueState::Set` which returns true + /// Check if the [ActiveValue] is [ActiveValue::Set] pub fn is_set(&self) -> bool { - matches!(self.state, ActiveValueState::Set) + matches!(self, Self::Set(_)) } - pub(crate) fn unchanged(value: V) -> Self { - Self { - value: Some(value), - state: ActiveValueState::Unchanged, - } + /// Create an [ActiveValue::Unchanged] + pub fn unchanged(value: V) -> Self { + Self::Unchanged(value) } - /// Check if the status of the [ActiveValue] is `ActiveValueState::Unchanged` - /// which returns `true` if it is + /// Check if the [ActiveValue] is [ActiveValue::Unchanged] pub fn is_unchanged(&self) -> bool { - matches!(self.state, ActiveValueState::Unchanged) + matches!(self, Self::Unchanged(_)) } - /// Set the `value` field of the ActiveModel to [Option::None] and the - /// `state` field to `ActiveValueState::Unset` - pub fn unset() -> Self { - Self { - value: None, - state: ActiveValueState::Unset, + /// Create an [ActiveValue::NotSet] + pub fn not_set() -> Self { + Self::default() + } + + /// Check if the [ActiveValue] is [ActiveValue::NotSet] + pub fn is_not_set(&self) -> bool { + matches!(self, Self::NotSet) + } + + /// Get the mutable value an [ActiveValue] + /// also setting itself to [ActiveValue::NotSet] + pub fn take(&mut self) -> Option { + match std::mem::take(self) { + ActiveValue::Set(value) | ActiveValue::Unchanged(value) => Some(value), + ActiveValue::NotSet => None, } } - /// Check if the state of an [ActiveValue] is `ActiveValueState::Unset` - /// which returns true if it is - pub fn is_unset(&self) -> bool { - matches!(self.state, ActiveValueState::Unset) - } - - /// Get the mutable value of the `value` field of an [ActiveValue] - /// also setting it's state to `ActiveValueState::Unset` - pub fn take(&mut self) -> Option { - self.state = ActiveValueState::Unset; - self.value.take() - } - - /// Get an owned value of the `value` field of the [ActiveValue] + /// Get an owned value of the [ActiveValue] pub fn unwrap(self) -> V { - self.value.unwrap() + match self { + ActiveValue::Set(value) | ActiveValue::Unchanged(value) => value, + ActiveValue::NotSet => panic!("Cannot unwrap ActiveValue::NotSet"), + } } /// Check is a [Value] exists or not pub fn into_value(self) -> Option { - self.value.map(Into::into) + match self { + ActiveValue::Set(value) | ActiveValue::Unchanged(value) => Some(value.into()), + ActiveValue::NotSet => None, + } } /// Wrap the [Value] into a `ActiveValue` pub fn into_wrapped_value(self) -> ActiveValue { - match self.state { - ActiveValueState::Set => ActiveValue::set(self.into_value().unwrap()), - ActiveValueState::Unchanged => ActiveValue::unchanged(self.into_value().unwrap()), - ActiveValueState::Unset => ActiveValue::unset(), + match self { + Self::Set(value) => ActiveValue::set(value.into()), + Self::Unchanged(value) => ActiveValue::unchanged(value.into()), + Self::NotSet => ActiveValue::not_set(), } } } @@ -690,7 +699,10 @@ where V: Into, { fn as_ref(&self) -> &V { - self.value.as_ref().unwrap() + match self { + ActiveValue::Set(value) | ActiveValue::Unchanged(value) => value, + ActiveValue::NotSet => panic!("Cannot borrow ActiveValue::NotSet"), + } } } @@ -699,7 +711,12 @@ where V: Into + std::cmp::PartialEq, { fn eq(&self, other: &Self) -> bool { - self.value.as_ref() == other.value.as_ref() + match (self, other) { + (ActiveValue::Set(l), ActiveValue::Set(r)) => l == r, + (ActiveValue::Unchanged(l), ActiveValue::Unchanged(r)) => l == r, + (ActiveValue::NotSet, ActiveValue::NotSet) => true, + _ => false, + } } } @@ -708,10 +725,10 @@ where V: Into + Nullable, { fn from(value: ActiveValue) -> Self { - match value.state { - ActiveValueState::Set => Set(value.value), - ActiveValueState::Unset => Unset(None), - ActiveValueState::Unchanged => ActiveValue::unchanged(value.value), + match value { + ActiveValue::Set(value) => ActiveValue::set(Some(value)), + ActiveValue::Unchanged(value) => ActiveValue::unchanged(Some(value)), + ActiveValue::NotSet => ActiveValue::not_set(), } } } @@ -746,7 +763,7 @@ mod tests { } .into_active_model(), fruit::ActiveModel { - id: Unset(None), + id: NotSet, name: Set("Apple".to_owned()), cake_id: Set(Some(1)), } @@ -775,8 +792,8 @@ mod tests { } .into_active_model(), fruit::ActiveModel { - id: Unset(None), - name: Unset(None), + id: NotSet, + name: NotSet, cake_id: Set(Some(1)), } ); @@ -787,8 +804,8 @@ mod tests { } .into_active_model(), fruit::ActiveModel { - id: Unset(None), - name: Unset(None), + id: NotSet, + name: NotSet, cake_id: Set(None), } ); @@ -796,9 +813,9 @@ mod tests { assert_eq!( my_fruit::UpdateFruit { cake_id: None }.into_active_model(), fruit::ActiveModel { - id: Unset(None), - name: Unset(None), - cake_id: Unset(None), + id: NotSet, + name: NotSet, + cake_id: NotSet, } ); } diff --git a/src/lib.rs b/src/lib.rs index f5387aeb..81cf98a8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -201,12 +201,12 @@ //! # use sea_orm::{DbConn, error::*, entity::*, query::*, tests_cfg::*}; //! # async fn function(db: &DbConn) -> Result<(), DbErr> { //! let banana = fruit::ActiveModel { -//! id: Unset(None), +//! id: NotSet, //! name: Set("Banana".to_owned()), //! ..Default::default() //! }; //! -//! // create, because primary key `id` is `Unset` +//! // create, because primary key `id` is `NotSet` //! let mut banana = banana.save(db).await?.into_active_model(); //! //! banana.name = Set("Banana Mongo".to_owned()); diff --git a/src/query/insert.rs b/src/query/insert.rs index 7cafc44c..563d6474 100644 --- a/src/query/insert.rs +++ b/src/query/insert.rs @@ -63,7 +63,7 @@ where /// /// assert_eq!( /// Insert::one(cake::ActiveModel { - /// id: Unset(None), + /// id: NotSet, /// name: Set("Apple Pie".to_owned()), /// }) /// .build(DbBackend::Postgres) @@ -190,7 +190,7 @@ mod tests { assert_eq!( Insert::::new() .add(cake::ActiveModel { - id: ActiveValue::unset(), + id: ActiveValue::not_set(), name: ActiveValue::set("Apple Pie".to_owned()), }) .build(DbBackend::Postgres) diff --git a/src/query/update.rs b/src/query/update.rs index f12d3b95..a48d19a5 100644 --- a/src/query/update.rs +++ b/src/query/update.rs @@ -236,7 +236,7 @@ mod tests { Update::one(fruit::ActiveModel { id: ActiveValue::set(1), name: ActiveValue::set("Orange".to_owned()), - cake_id: ActiveValue::unset(), + cake_id: ActiveValue::not_set(), }) .build(DbBackend::Postgres) .to_string(), diff --git a/tests/basic.rs b/tests/basic.rs index 96eed084..51f300da 100644 --- a/tests/basic.rs +++ b/tests/basic.rs @@ -53,8 +53,8 @@ async fn crud_cake(db: &DbConn) -> Result<(), DbErr> { assert_eq!( apple, cake::ActiveModel { - id: Set(1), - name: Set("Apple Pie".to_owned()), + id: Unchanged(1), + name: Unchanged("Apple Pie".to_owned()), } ); From 09fd9ba7251c46ae67f7c7221cf345ef0baf74ec Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sun, 19 Dec 2021 02:22:02 +0800 Subject: [PATCH 30/36] Docs --- src/entity/active_model.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/entity/active_model.rs b/src/entity/active_model.rs index d4f635c0..d01145e3 100644 --- a/src/entity/active_model.rs +++ b/src/entity/active_model.rs @@ -10,9 +10,9 @@ pub use ActiveValue::NotSet; /// Defines a stateful value used in ActiveModel. /// /// There are three possible state represented by three enum variants. -/// - [ActiveValue::Set]: A [Value] was set -/// - [ActiveValue::Unchanged]: A [Value] remain unchanged -/// - [ActiveValue::NotSet]: A NULL value similar to [Option::None] +/// - [ActiveValue::Set]: A defined [Value] actively being set +/// - [ActiveValue::Unchanged]: A defined [Value] remain unchanged +/// - [ActiveValue::NotSet]: An undefined [Value] /// /// The stateful value is useful when constructing UPDATE SQL statement, /// see an example below. @@ -40,11 +40,11 @@ pub enum ActiveValue where V: Into, { - /// A [Value] was set + /// A defined [Value] actively being set Set(V), - /// A [Value] remain unchanged + /// A defined [Value] remain unchanged Unchanged(V), - /// A NULL value similar to [Option::None] + /// An undefined [Value] NotSet, } From 17631512bbfe3e2a3055477905083d4a8b6dab18 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Tue, 21 Dec 2021 18:13:51 +0800 Subject: [PATCH 31/36] feat(Model): add wrapper method delete --- README.md | 12 ++++++++---- src/entity/model.rs | 17 +++++++++++++++-- src/lib.rs | 13 ++++++++----- tests/active_enum_tests.rs | 2 +- tests/basic.rs | 2 +- tests/crud/deletes.rs | 12 ++---------- tests/crud/updates.rs | 2 +- tests/sequential_op_tests.rs | 3 +-- tests/transaction_tests.rs | 4 ++-- 9 files changed, 39 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 636fe594..9f6e635d 100644 --- a/README.md +++ b/README.md @@ -152,12 +152,16 @@ let banana = banana.save(db).await?; ``` ### Delete ```rust -let orange: Option = Fruit::find_by_id(1).one(db).await?; -let orange: fruit::ActiveModel = orange.unwrap().into(); - // delete one -fruit::Entity::delete(orange).exec(db).await?; +let orange: Option = Fruit::find_by_id(1).one(db).await?; +let orange: fruit::Model = orange.unwrap(); +fruit::Entity::delete(orange.into_active_model()) + .exec(db) + .await?; + // or simply +let orange: Option = Fruit::find_by_id(1).one(db).await?; +let orange: fruit::Model = orange.unwrap(); orange.delete(db).await?; // delete many: DELETE FROM "fruit" WHERE "fruit"."name" LIKE 'Orange' diff --git a/src/entity/model.rs b/src/entity/model.rs index acea83d6..271493ef 100644 --- a/src/entity/model.rs +++ b/src/entity/model.rs @@ -1,11 +1,14 @@ use crate::{ - DbErr, EntityTrait, Linked, QueryFilter, QueryResult, Related, Select, SelectModel, - SelectorRaw, Statement, + ActiveModelBehavior, ActiveModelTrait, ConnectionTrait, DbErr, DeleteResult, EntityTrait, + IntoActiveModel, Linked, QueryFilter, QueryResult, Related, Select, SelectModel, SelectorRaw, + Statement, }; +use async_trait::async_trait; pub use sea_query::Value; use std::fmt::Debug; /// A Trait for a Model +#[async_trait] pub trait ModelTrait: Clone + Send + Debug { #[allow(missing_docs)] type Entity: EntityTrait; @@ -33,6 +36,16 @@ pub trait ModelTrait: Clone + Send + Debug { let tbl_alias = &format!("r{}", l.link().len() - 1); l.find_linked().belongs_to_tbl_alias(self, tbl_alias) } + + /// Delete an model + async fn delete<'a, A, C>(self, db: &'a C) -> Result + where + Self: IntoActiveModel, + C: ConnectionTrait<'a>, + A: ActiveModelTrait + ActiveModelBehavior + Send + 'a, + { + self.into_active_model().delete(db).await + } } /// A Trait for implementing a [QueryResult] diff --git a/src/lib.rs b/src/lib.rs index 81cf98a8..d1dde905 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -221,13 +221,16 @@ //! ``` //! # use sea_orm::{DbConn, error::*, entity::*, query::*, tests_cfg::*}; //! # async fn function(db: &DbConn) -> Result<(), DbErr> { -//! let orange: Option = Fruit::find_by_id(1).one(db).await?; -//! let orange: fruit::ActiveModel = orange.unwrap().into(); -//! //! // delete one -//! fruit::Entity::delete(orange).exec(db).await?; +//! let orange: Option = Fruit::find_by_id(1).one(db).await?; +//! let orange: fruit::Model = orange.unwrap(); +//! fruit::Entity::delete(orange.into_active_model()) +//! .exec(db) +//! .await?; +//! //! // or simply -//! # let orange: fruit::ActiveModel = Fruit::find_by_id(1).one(db).await.unwrap().unwrap().into(); +//! let orange: Option = Fruit::find_by_id(1).one(db).await?; +//! let orange: fruit::Model = orange.unwrap(); //! orange.delete(db).await?; //! //! // delete many: DELETE FROM "fruit" WHERE "fruit"."name" LIKE 'Orange' diff --git a/tests/active_enum_tests.rs b/tests/active_enum_tests.rs index 4904cb40..7aae2002 100644 --- a/tests/active_enum_tests.rs +++ b/tests/active_enum_tests.rs @@ -89,7 +89,7 @@ pub async fn insert_active_enum(db: &DatabaseConnection) -> Result<(), DbErr> { .unwrap() ); - let res = model.into_active_model().delete(db).await?; + let res = model.delete(db).await?; assert_eq!(res.rows_affected, 1); assert_eq!(Entity::find().one(db).await?, None); diff --git a/tests/basic.rs b/tests/basic.rs index 51f300da..d7d342d1 100644 --- a/tests/basic.rs +++ b/tests/basic.rs @@ -81,7 +81,7 @@ async fn crud_cake(db: &DbConn) -> Result<(), DbErr> { apple ); - let apple: cake::ActiveModel = apple.unwrap().into(); + let apple: cake::Model = apple.unwrap(); let result = apple.delete(db).await?; diff --git a/tests/crud/deletes.rs b/tests/crud/deletes.rs index 01cfc7c2..4c34d36b 100644 --- a/tests/crud/deletes.rs +++ b/tests/crud/deletes.rs @@ -29,11 +29,7 @@ pub async fn test_delete_cake(db: &DbConn) { let cakes = Cake::find().all(db).await.unwrap(); assert_eq!(cakes.len(), initial_cakes + 1); - let _result = cake - .into_active_model() - .delete(db) - .await - .expect("failed to delete cake"); + let _result = cake.delete(db).await.expect("failed to delete cake"); let cakes = Cake::find().all(db).await.unwrap(); assert_eq!(cakes.len(), initial_cakes); @@ -56,11 +52,7 @@ pub async fn test_delete_bakery(db: &DbConn) { initial_bakeries + 1 ); - let _result = bakery - .into_active_model() - .delete(db) - .await - .expect("failed to delete bakery"); + let _result = bakery.delete(db).await.expect("failed to delete bakery"); assert_eq!( Bakery::find().all(db).await.unwrap().len(), diff --git a/tests/crud/updates.rs b/tests/crud/updates.rs index b8ea6eb7..6c3cf690 100644 --- a/tests/crud/updates.rs +++ b/tests/crud/updates.rs @@ -110,7 +110,7 @@ pub async fn test_update_deleted_customer(db: &DbConn) { let customer_id = customer.id; - let _ = customer.into_active_model().delete(db).await; + let _ = customer.delete(db).await; assert_eq!(Customer::find().count(db).await.unwrap(), init_n_customers); let customer = customer::ActiveModel { diff --git a/tests/sequential_op_tests.rs b/tests/sequential_op_tests.rs index 8c7120c0..de2e0dd8 100644 --- a/tests/sequential_op_tests.rs +++ b/tests/sequential_op_tests.rs @@ -276,8 +276,7 @@ pub async fn test_delete_bakery(db: &DatabaseConnection) { } .save(db) .await - .expect("could not insert bakery") - .into_active_model(); + .expect("could not insert bakery"); assert_eq!( Bakery::find().all(db).await.unwrap().len(), diff --git a/tests/transaction_tests.rs b/tests/transaction_tests.rs index 34b8df22..7845843e 100644 --- a/tests/transaction_tests.rs +++ b/tests/transaction_tests.rs @@ -408,7 +408,7 @@ pub async fn transaction_with_active_model_behaviour() -> Result<(), DbErr> { assert_eq!(cake::Entity::find().all(&txn).await?.len(), 2); assert_eq!( - readonly_cake_1.into_active_model().delete(&txn).await.err(), + readonly_cake_1.delete(&txn).await.err(), Some(DbErr::Custom( "[before_delete] Cannot be deleted".to_owned() )) @@ -428,7 +428,7 @@ pub async fn transaction_with_active_model_behaviour() -> Result<(), DbErr> { assert_eq!(cake::Entity::find().all(&txn).await?.len(), 3); assert_eq!( - readonly_cake_2.into_active_model().delete(&txn).await.err(), + readonly_cake_2.delete(&txn).await.err(), Some(DbErr::Custom("[after_delete] Cannot be deleted".to_owned())) ); From 96a776ae9da4fe041b624f16718e503dc16d3118 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Wed, 22 Dec 2021 16:14:17 +0800 Subject: [PATCH 32/36] test(Schema): add test cases for `Schema::create_enum_from_entity` & `Schema::create_enum_from_active_enum` --- tests/active_enum_tests.rs | 28 ++++++++++++++++++++++++++++ tests/common/features/schema.rs | 18 +++++++++++++----- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/tests/active_enum_tests.rs b/tests/active_enum_tests.rs index 4904cb40..bfb3c5db 100644 --- a/tests/active_enum_tests.rs +++ b/tests/active_enum_tests.rs @@ -686,4 +686,32 @@ mod tests { .join(" ") ); } + + #[test] + fn create_enum_from() { + use sea_orm::{Schema, Statement}; + + let db_postgres = DbBackend::Postgres; + let schema = Schema::new(db_postgres); + + assert_eq!( + schema + .create_enum_from_entity(active_enum::Entity) + .iter() + .map(|stmt| db_postgres.build(stmt)) + .collect::>(), + vec![Statement::from_string( + db_postgres, + r#"CREATE TYPE "tea" AS ENUM ('EverydayTea', 'BreakfastTea')"#.to_owned() + ),] + ); + + assert_eq!( + db_postgres.build(&schema.create_enum_from_active_enum::()), + Statement::from_string( + db_postgres, + r#"CREATE TYPE "tea" AS ENUM ('EverydayTea', 'BreakfastTea')"#.to_owned() + ) + ); + } } diff --git a/tests/common/features/schema.rs b/tests/common/features/schema.rs index 91712c91..c38feb04 100644 --- a/tests/common/features/schema.rs +++ b/tests/common/features/schema.rs @@ -4,7 +4,7 @@ use super::*; use crate::common::setup::{create_enum, create_table, create_table_without_asserts}; use sea_orm::{ error::*, sea_query, ConnectionTrait, DatabaseConnection, DbBackend, DbConn, EntityName, - ExecResult, + ExecResult, Schema, }; use sea_query::{extension::postgres::Type, Alias, ColumnDef, ForeignKeyCreateStatement}; @@ -19,10 +19,18 @@ pub async fn create_tables(db: &DatabaseConnection) -> Result<(), DbErr> { let create_enum_stmts = match db_backend { DbBackend::MySql | DbBackend::Sqlite => Vec::new(), - DbBackend::Postgres => vec![Type::create() - .as_enum(Alias::new("tea")) - .values(vec![Alias::new("EverydayTea"), Alias::new("BreakfastTea")]) - .to_owned()], + DbBackend::Postgres => { + let schema = Schema::new(db_backend); + let enum_create_stmt = Type::create() + .as_enum(Alias::new("tea")) + .values(vec![Alias::new("EverydayTea"), Alias::new("BreakfastTea")]) + .to_owned(); + assert_eq!( + db_backend.build(&enum_create_stmt), + db_backend.build(&schema.create_enum_from_active_enum::()) + ); + vec![enum_create_stmt] + } }; create_enum(db, &create_enum_stmts, ActiveEnum).await?; From 2d5aa2a61b3db0efdc4cd08320861955b89fa5cd Mon Sep 17 00:00:00 2001 From: Billy Chan <30400950+billy1624@users.noreply.github.com> Date: Fri, 24 Dec 2021 23:59:37 +0800 Subject: [PATCH 33/36] Log with tracing-subscriber (#399) * chore: log examples with tracing-subscriber * chore: log [issues] with tracing-subscriber * chore: log [cli] with tracing-subscriber * feat: tracing will emit log if tracing-subscriber is not setup --- Cargo.toml | 2 +- examples/actix4_example/Cargo.toml | 4 ++-- examples/actix4_example/src/main.rs | 2 +- examples/actix_example/Cargo.toml | 4 ++-- examples/actix_example/src/main.rs | 2 +- examples/axum_example/Cargo.toml | 4 ++-- examples/axum_example/src/main.rs | 2 +- issues/86/Cargo.toml | 4 ++-- issues/86/src/main.rs | 6 +++--- sea-orm-cli/Cargo.toml | 4 ++-- sea-orm-cli/src/main.rs | 7 +++---- 11 files changed, 20 insertions(+), 21 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 443e2eb0..0eccf60d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ async-trait = { version = "^0.1" } chrono = { version = "^0", optional = true } futures = { version = "^0.3" } futures-util = { version = "^0.3" } -tracing = "0.1" +tracing = { version = "0.1", features = ["log"] } rust_decimal = { version = "^1", optional = true } sea-orm-macros = { version = "^0.4.2", path = "sea-orm-macros", optional = true } sea-query = { version = "^0.20.0", features = ["thread-safe"] } diff --git a/examples/actix4_example/Cargo.toml b/examples/actix4_example/Cargo.toml index b8721ce1..c7fea10a 100644 --- a/examples/actix4_example/Cargo.toml +++ b/examples/actix4_example/Cargo.toml @@ -18,12 +18,12 @@ tera = "1.8.0" dotenv = "0.15" listenfd = "0.3.3" serde = "1" -env_logger = "0.8" +tracing-subscriber = { version = "0.3", features = ["env-filter"] } [dependencies.sea-orm] path = "../../" # remove this line in your own project version = "^0.4.0" -features = ["macros", "runtime-actix-native-tls"] +features = ["macros", "runtime-actix-native-tls", "debug-print"] default-features = false [features] diff --git a/examples/actix4_example/src/main.rs b/examples/actix4_example/src/main.rs index 6a52b81b..43ec4336 100644 --- a/examples/actix4_example/src/main.rs +++ b/examples/actix4_example/src/main.rs @@ -155,7 +155,7 @@ async fn delete(data: web::Data, id: web::Path) -> Result std::io::Result<()> { std::env::set_var("RUST_LOG", "debug"); - env_logger::init(); + tracing_subscriber::fmt::init(); // get env vars dotenv::dotenv().ok(); diff --git a/examples/actix_example/Cargo.toml b/examples/actix_example/Cargo.toml index 368d4d62..36cbf842 100644 --- a/examples/actix_example/Cargo.toml +++ b/examples/actix_example/Cargo.toml @@ -18,12 +18,12 @@ tera = "1.8.0" dotenv = "0.15" listenfd = "0.3.3" serde = "1" -env_logger = "0.8" +tracing-subscriber = { version = "0.3", features = ["env-filter"] } [dependencies.sea-orm] path = "../../" # remove this line in your own project version = "^0.4.0" -features = ["macros", "runtime-async-std-native-tls"] +features = ["macros", "runtime-async-std-native-tls", "debug-print"] default-features = false [features] diff --git a/examples/actix_example/src/main.rs b/examples/actix_example/src/main.rs index e2d1e956..d532174f 100644 --- a/examples/actix_example/src/main.rs +++ b/examples/actix_example/src/main.rs @@ -181,7 +181,7 @@ async fn delete( #[actix_web::main] async fn main() -> std::io::Result<()> { std::env::set_var("RUST_LOG", "debug"); - env_logger::init(); + tracing_subscriber::fmt::init(); // get env vars dotenv::dotenv().ok(); diff --git a/examples/axum_example/Cargo.toml b/examples/axum_example/Cargo.toml index 3b07ce6d..07994151 100644 --- a/examples/axum_example/Cargo.toml +++ b/examples/axum_example/Cargo.toml @@ -16,15 +16,15 @@ tower-http = { version = "0.2", features = ["fs"] } tower-cookies = { version = "0.4" } anyhow = "1" dotenv = "0.15" -env_logger = "0.9" serde = "1" serde_json = "1" tera = "1" +tracing-subscriber = { version = "0.3", features = ["env-filter"] } [dependencies.sea-orm] path = "../../" # remove this line in your own project version = "^0.4.2" -features = ["macros", "runtime-tokio-native-tls"] +features = ["macros", "runtime-tokio-native-tls", "debug-print"] default-features = false [features] diff --git a/examples/axum_example/src/main.rs b/examples/axum_example/src/main.rs index 5c48d9dc..c35e180a 100644 --- a/examples/axum_example/src/main.rs +++ b/examples/axum_example/src/main.rs @@ -23,7 +23,7 @@ use tower_http::services::ServeDir; #[tokio::main] async fn main() -> anyhow::Result<()> { env::set_var("RUST_LOG", "debug"); - env_logger::init(); + tracing_subscriber::fmt::init(); dotenv::dotenv().ok(); let db_url = env::var("DATABASE_URL").expect("DATABASE_URL is not set in .env file"); diff --git a/issues/86/Cargo.toml b/issues/86/Cargo.toml index 4284cb68..f5749a63 100644 --- a/issues/86/Cargo.toml +++ b/issues/86/Cargo.toml @@ -10,5 +10,5 @@ publish = false [dependencies] sea-orm = { path = "../../", features = [ "sqlx-all", "runtime-tokio-native-tls", "debug-print" ] } tokio = { version = "1", features = ["full"] } -env_logger = { version = "^0.9" } -log = { version = "^0.4" } +tracing-subscriber = { version = "0.3", features = ["env-filter"] } +tracing = { version = "0.1" } diff --git a/issues/86/src/main.rs b/issues/86/src/main.rs index 14a76086..21681287 100644 --- a/issues/86/src/main.rs +++ b/issues/86/src/main.rs @@ -3,9 +3,9 @@ use sea_orm::*; #[tokio::main] pub async fn main() { - env_logger::builder() - .filter_level(log::LevelFilter::Debug) - .is_test(true) + tracing_subscriber::fmt() + .with_max_level(tracing::Level::DEBUG) + .with_test_writer() .init(); let db = Database::connect("mysql://sea:sea@localhost/bakery") diff --git a/sea-orm-cli/Cargo.toml b/sea-orm-cli/Cargo.toml index 0c8a0660..6dca13bb 100644 --- a/sea-orm-cli/Cargo.toml +++ b/sea-orm-cli/Cargo.toml @@ -30,8 +30,8 @@ sea-schema = { version = "0.3.0", default-features = false, features = [ "writer", ] } sqlx = { version = "^0.5", default-features = false, features = [ "mysql", "postgres" ] } -env_logger = { version = "^0.9" } -log = { version = "^0.4" } +tracing-subscriber = { version = "0.3", features = ["env-filter"] } +tracing = { version = "0.1" } url = "^2.2" [dev-dependencies] diff --git a/sea-orm-cli/src/main.rs b/sea-orm-cli/src/main.rs index 2c7848ce..aee80b0b 100644 --- a/sea-orm-cli/src/main.rs +++ b/sea-orm-cli/src/main.rs @@ -1,6 +1,5 @@ use clap::ArgMatches; use dotenv::dotenv; -use log::LevelFilter; use sea_orm_codegen::{EntityTransformer, OutputFile, WithSerde}; use std::{error::Error, fmt::Display, fs, io::Write, path::Path, process::Command, str::FromStr}; use url::Url; @@ -33,9 +32,9 @@ async fn run_generate_command(matches: &ArgMatches<'_>) -> Result<(), Box Date: Sat, 25 Dec 2021 11:31:47 +0800 Subject: [PATCH 34/36] Codegen SQLite (#386) * Codegen SQLite * Remove debugging * Fixup * Add SQLite "sakila.db" demo [issues] --- .github/workflows/rust.yml | 2 +- issues/386/Cargo.toml | 11 ++ issues/386/src/compact/actor.rs | 27 +++++ issues/386/src/compact/address.rs | 61 +++++++++++ issues/386/src/compact/category.rs | 30 ++++++ issues/386/src/compact/city.rs | 42 ++++++++ issues/386/src/compact/country.rs | 30 ++++++ issues/386/src/compact/customer.rs | 69 ++++++++++++ issues/386/src/compact/film.rs | 75 +++++++++++++ issues/386/src/compact/film_actor.rs | 47 ++++++++ issues/386/src/compact/film_category.rs | 51 +++++++++ issues/386/src/compact/film_text.rs | 28 +++++ issues/386/src/compact/inventory.rs | 55 ++++++++++ issues/386/src/compact/language.rs | 28 +++++ issues/386/src/compact/mod.rs | 20 ++++ issues/386/src/compact/payment.rs | 66 ++++++++++++ issues/386/src/compact/prelude.rs | 18 ++++ issues/386/src/compact/rental.rs | 73 +++++++++++++ issues/386/src/compact/staff.rs | 76 +++++++++++++ issues/386/src/compact/store.rs | 64 +++++++++++ issues/386/src/expanded/actor.rs | 73 +++++++++++++ issues/386/src/expanded/address.rs | 112 +++++++++++++++++++ issues/386/src/expanded/category.rs | 70 ++++++++++++ issues/386/src/expanded/city.rs | 84 +++++++++++++++ issues/386/src/expanded/country.rs | 70 ++++++++++++ issues/386/src/expanded/customer.rs | 118 ++++++++++++++++++++ issues/386/src/expanded/film.rs | 126 ++++++++++++++++++++++ issues/386/src/expanded/film_actor.rs | 85 +++++++++++++++ issues/386/src/expanded/film_category.rs | 85 +++++++++++++++ issues/386/src/expanded/film_text.rs | 60 +++++++++++ issues/386/src/expanded/inventory.rs | 95 ++++++++++++++++ issues/386/src/expanded/language.rs | 60 +++++++++++ issues/386/src/expanded/mod.rs | 20 ++++ issues/386/src/expanded/payment.rs | 107 ++++++++++++++++++ issues/386/src/expanded/prelude.rs | 18 ++++ issues/386/src/expanded/rental.rs | 115 ++++++++++++++++++++ issues/386/src/expanded/staff.rs | 124 +++++++++++++++++++++ issues/386/src/expanded/store.rs | 103 ++++++++++++++++++ issues/386/src/main.rs | 4 + sea-orm-cli/Cargo.toml | 3 +- sea-orm-cli/README.md | 5 +- sea-orm-cli/src/main.rs | 90 ++++++++++------ sea-orm-codegen/src/entity/transformer.rs | 69 +++++++----- 43 files changed, 2506 insertions(+), 63 deletions(-) create mode 100644 issues/386/Cargo.toml create mode 100644 issues/386/src/compact/actor.rs create mode 100644 issues/386/src/compact/address.rs create mode 100644 issues/386/src/compact/category.rs create mode 100644 issues/386/src/compact/city.rs create mode 100644 issues/386/src/compact/country.rs create mode 100644 issues/386/src/compact/customer.rs create mode 100644 issues/386/src/compact/film.rs create mode 100644 issues/386/src/compact/film_actor.rs create mode 100644 issues/386/src/compact/film_category.rs create mode 100644 issues/386/src/compact/film_text.rs create mode 100644 issues/386/src/compact/inventory.rs create mode 100644 issues/386/src/compact/language.rs create mode 100644 issues/386/src/compact/mod.rs create mode 100644 issues/386/src/compact/payment.rs create mode 100644 issues/386/src/compact/prelude.rs create mode 100644 issues/386/src/compact/rental.rs create mode 100644 issues/386/src/compact/staff.rs create mode 100644 issues/386/src/compact/store.rs create mode 100644 issues/386/src/expanded/actor.rs create mode 100644 issues/386/src/expanded/address.rs create mode 100644 issues/386/src/expanded/category.rs create mode 100644 issues/386/src/expanded/city.rs create mode 100644 issues/386/src/expanded/country.rs create mode 100644 issues/386/src/expanded/customer.rs create mode 100644 issues/386/src/expanded/film.rs create mode 100644 issues/386/src/expanded/film_actor.rs create mode 100644 issues/386/src/expanded/film_category.rs create mode 100644 issues/386/src/expanded/film_text.rs create mode 100644 issues/386/src/expanded/inventory.rs create mode 100644 issues/386/src/expanded/language.rs create mode 100644 issues/386/src/expanded/mod.rs create mode 100644 issues/386/src/expanded/payment.rs create mode 100644 issues/386/src/expanded/prelude.rs create mode 100644 issues/386/src/expanded/rental.rs create mode 100644 issues/386/src/expanded/staff.rs create mode 100644 issues/386/src/expanded/store.rs create mode 100644 issues/386/src/main.rs diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 4affff66..b9618904 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -316,7 +316,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - path: [86, 249, 262, 319, 324, 352, 356] + path: [86, 249, 262, 319, 324, 352, 356, 386] steps: - uses: actions/checkout@v2 diff --git a/issues/386/Cargo.toml b/issues/386/Cargo.toml new file mode 100644 index 00000000..f3a975f1 --- /dev/null +++ b/issues/386/Cargo.toml @@ -0,0 +1,11 @@ +[workspace] +# A separate workspace + +[package] +name = "sea-orm-issues-386" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +sea-orm = { path = "../../", features = [ "sqlx-mysql", "runtime-async-std-native-tls" ]} diff --git a/issues/386/src/compact/actor.rs b/issues/386/src/compact/actor.rs new file mode 100644 index 00000000..ad7248d6 --- /dev/null +++ b/issues/386/src/compact/actor.rs @@ -0,0 +1,27 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "actor")] +pub struct Model { + #[sea_orm(primary_key)] + pub actor_id: i32, + pub first_name: String, + pub last_name: String, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::film_actor::Entity")] + FilmActor, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::FilmActor.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/address.rs b/issues/386/src/compact/address.rs new file mode 100644 index 00000000..04541e3c --- /dev/null +++ b/issues/386/src/compact/address.rs @@ -0,0 +1,61 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "address")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub address_id: i32, + pub address: String, + pub address2: Option, + pub district: String, + pub city_id: i32, + pub postal_code: Option, + pub phone: String, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::city::Entity", + from = "Column::CityId", + to = "super::city::Column::CityId", + on_update = "Cascade", + on_delete = "NoAction" + )] + City, + #[sea_orm(has_many = "super::customer::Entity")] + Customer, + #[sea_orm(has_many = "super::staff::Entity")] + Staff, + #[sea_orm(has_many = "super::store::Entity")] + Store, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::City.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Customer.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Staff.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Store.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/category.rs b/issues/386/src/compact/category.rs new file mode 100644 index 00000000..a7ff20f3 --- /dev/null +++ b/issues/386/src/compact/category.rs @@ -0,0 +1,30 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "category")] +pub struct Model { + #[sea_orm( + primary_key, + auto_increment = false, + column_type = "Custom(\"BLOB\".to_owned())" + )] + pub category_id: String, + pub name: String, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::film_category::Entity")] + FilmCategory, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::FilmCategory.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/city.rs b/issues/386/src/compact/city.rs new file mode 100644 index 00000000..02d28b0d --- /dev/null +++ b/issues/386/src/compact/city.rs @@ -0,0 +1,42 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "city")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub city_id: i32, + pub city: String, + #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())")] + pub country_id: String, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::country::Entity", + from = "Column::CountryId", + to = "super::country::Column::CountryId", + on_update = "Cascade", + on_delete = "NoAction" + )] + Country, + #[sea_orm(has_many = "super::address::Entity")] + Address, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Country.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Address.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/country.rs b/issues/386/src/compact/country.rs new file mode 100644 index 00000000..9fe96829 --- /dev/null +++ b/issues/386/src/compact/country.rs @@ -0,0 +1,30 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "country")] +pub struct Model { + #[sea_orm( + primary_key, + auto_increment = false, + column_type = "Custom(\"BLOB\".to_owned())" + )] + pub country_id: String, + pub country: String, + pub last_update: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::city::Entity")] + City, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::City.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/customer.rs b/issues/386/src/compact/customer.rs new file mode 100644 index 00000000..95807b65 --- /dev/null +++ b/issues/386/src/compact/customer.rs @@ -0,0 +1,69 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "customer")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub customer_id: i32, + pub store_id: i32, + pub first_name: String, + pub last_name: String, + pub email: Option, + pub address_id: i32, + #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())")] + pub active: String, + pub create_date: DateTime, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::address::Entity", + from = "Column::AddressId", + to = "super::address::Column::AddressId", + on_update = "Cascade", + on_delete = "NoAction" + )] + Address, + #[sea_orm( + belongs_to = "super::store::Entity", + from = "Column::StoreId", + to = "super::store::Column::StoreId", + on_update = "Cascade", + on_delete = "NoAction" + )] + Store, + #[sea_orm(has_many = "super::payment::Entity")] + Payment, + #[sea_orm(has_many = "super::rental::Entity")] + Rental, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Address.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Store.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Payment.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Rental.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/film.rs b/issues/386/src/compact/film.rs new file mode 100644 index 00000000..39cf0330 --- /dev/null +++ b/issues/386/src/compact/film.rs @@ -0,0 +1,75 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "film")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub film_id: i32, + pub title: String, + #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())", nullable)] + pub description: Option, + pub release_year: Option, + #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())")] + pub language_id: String, + #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())", nullable)] + pub original_language_id: Option, + #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())")] + pub rental_duration: String, + #[sea_orm(column_type = "Decimal(Some((4, 2)))")] + pub rental_rate: Decimal, + #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())", nullable)] + pub length: Option, + #[sea_orm(column_type = "Decimal(Some((5, 2)))")] + pub replacement_cost: Decimal, + pub rating: Option, + pub special_features: Option, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::language::Entity", + from = "Column::OriginalLanguageId", + to = "super::language::Column::LanguageId", + on_update = "NoAction", + on_delete = "NoAction" + )] + Language2, + #[sea_orm( + belongs_to = "super::language::Entity", + from = "Column::LanguageId", + to = "super::language::Column::LanguageId", + on_update = "NoAction", + on_delete = "NoAction" + )] + Language1, + #[sea_orm(has_many = "super::film_actor::Entity")] + FilmActor, + #[sea_orm(has_many = "super::film_category::Entity")] + FilmCategory, + #[sea_orm(has_many = "super::inventory::Entity")] + Inventory, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::FilmActor.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::FilmCategory.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Inventory.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/film_actor.rs b/issues/386/src/compact/film_actor.rs new file mode 100644 index 00000000..ba23ccb7 --- /dev/null +++ b/issues/386/src/compact/film_actor.rs @@ -0,0 +1,47 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "film_actor")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub actor_id: i32, + #[sea_orm(primary_key, auto_increment = false)] + pub film_id: i32, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::film::Entity", + from = "Column::FilmId", + to = "super::film::Column::FilmId", + on_update = "Cascade", + on_delete = "NoAction" + )] + Film, + #[sea_orm( + belongs_to = "super::actor::Entity", + from = "Column::ActorId", + to = "super::actor::Column::ActorId", + on_update = "Cascade", + on_delete = "NoAction" + )] + Actor, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Film.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Actor.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/film_category.rs b/issues/386/src/compact/film_category.rs new file mode 100644 index 00000000..222a773a --- /dev/null +++ b/issues/386/src/compact/film_category.rs @@ -0,0 +1,51 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "film_category")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub film_id: i32, + #[sea_orm( + primary_key, + auto_increment = false, + column_type = "Custom(\"BLOB\".to_owned())" + )] + pub category_id: String, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::category::Entity", + from = "Column::CategoryId", + to = "super::category::Column::CategoryId", + on_update = "Cascade", + on_delete = "NoAction" + )] + Category, + #[sea_orm( + belongs_to = "super::film::Entity", + from = "Column::FilmId", + to = "super::film::Column::FilmId", + on_update = "Cascade", + on_delete = "NoAction" + )] + Film, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Category.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Film.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/film_text.rs b/issues/386/src/compact/film_text.rs new file mode 100644 index 00000000..d8f26b69 --- /dev/null +++ b/issues/386/src/compact/film_text.rs @@ -0,0 +1,28 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "film_text")] +pub struct Model { + #[sea_orm( + primary_key, + auto_increment = false, + column_type = "Custom(\"BLOB\".to_owned())" + )] + pub film_id: String, + pub title: String, + #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())", nullable)] + pub description: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation {} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + panic!("No RelationDef") + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/inventory.rs b/issues/386/src/compact/inventory.rs new file mode 100644 index 00000000..2f71f5c4 --- /dev/null +++ b/issues/386/src/compact/inventory.rs @@ -0,0 +1,55 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "inventory")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub inventory_id: i32, + pub film_id: i32, + pub store_id: i32, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::film::Entity", + from = "Column::FilmId", + to = "super::film::Column::FilmId", + on_update = "Cascade", + on_delete = "NoAction" + )] + Film, + #[sea_orm( + belongs_to = "super::store::Entity", + from = "Column::StoreId", + to = "super::store::Column::StoreId", + on_update = "Cascade", + on_delete = "NoAction" + )] + Store, + #[sea_orm(has_many = "super::rental::Entity")] + Rental, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Film.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Store.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Rental.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/language.rs b/issues/386/src/compact/language.rs new file mode 100644 index 00000000..d77db368 --- /dev/null +++ b/issues/386/src/compact/language.rs @@ -0,0 +1,28 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "language")] +pub struct Model { + #[sea_orm( + primary_key, + auto_increment = false, + column_type = "Custom(\"BLOB\".to_owned())" + )] + pub language_id: String, + #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())")] + pub name: String, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation {} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + panic!("No RelationDef") + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/mod.rs b/issues/386/src/compact/mod.rs new file mode 100644 index 00000000..d7f098fc --- /dev/null +++ b/issues/386/src/compact/mod.rs @@ -0,0 +1,20 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +pub mod prelude; + +pub mod actor; +pub mod address; +pub mod category; +pub mod city; +pub mod country; +pub mod customer; +pub mod film; +pub mod film_actor; +pub mod film_category; +pub mod film_text; +pub mod inventory; +pub mod language; +pub mod payment; +pub mod rental; +pub mod staff; +pub mod store; diff --git a/issues/386/src/compact/payment.rs b/issues/386/src/compact/payment.rs new file mode 100644 index 00000000..43c494b4 --- /dev/null +++ b/issues/386/src/compact/payment.rs @@ -0,0 +1,66 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "payment")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub payment_id: i32, + pub customer_id: i32, + #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())")] + pub staff_id: String, + pub rental_id: Option, + #[sea_orm(column_type = "Decimal(Some((5, 2)))")] + pub amount: Decimal, + pub payment_date: DateTime, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::staff::Entity", + from = "Column::StaffId", + to = "super::staff::Column::StaffId", + on_update = "NoAction", + on_delete = "NoAction" + )] + Staff, + #[sea_orm( + belongs_to = "super::customer::Entity", + from = "Column::CustomerId", + to = "super::customer::Column::CustomerId", + on_update = "NoAction", + on_delete = "NoAction" + )] + Customer, + #[sea_orm( + belongs_to = "super::rental::Entity", + from = "Column::RentalId", + to = "super::rental::Column::RentalId", + on_update = "Cascade", + on_delete = "SetNull" + )] + Rental, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Staff.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Customer.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Rental.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/prelude.rs b/issues/386/src/compact/prelude.rs new file mode 100644 index 00000000..85cecd87 --- /dev/null +++ b/issues/386/src/compact/prelude.rs @@ -0,0 +1,18 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +pub use super::actor::Entity as Actor; +pub use super::address::Entity as Address; +pub use super::category::Entity as Category; +pub use super::city::Entity as City; +pub use super::country::Entity as Country; +pub use super::customer::Entity as Customer; +pub use super::film::Entity as Film; +pub use super::film_actor::Entity as FilmActor; +pub use super::film_category::Entity as FilmCategory; +pub use super::film_text::Entity as FilmText; +pub use super::inventory::Entity as Inventory; +pub use super::language::Entity as Language; +pub use super::payment::Entity as Payment; +pub use super::rental::Entity as Rental; +pub use super::staff::Entity as Staff; +pub use super::store::Entity as Store; diff --git a/issues/386/src/compact/rental.rs b/issues/386/src/compact/rental.rs new file mode 100644 index 00000000..15c7e9d9 --- /dev/null +++ b/issues/386/src/compact/rental.rs @@ -0,0 +1,73 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "rental")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub rental_id: i32, + pub rental_date: DateTime, + pub inventory_id: i32, + pub customer_id: i32, + pub return_date: Option, + #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())")] + pub staff_id: String, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::customer::Entity", + from = "Column::CustomerId", + to = "super::customer::Column::CustomerId", + on_update = "NoAction", + on_delete = "NoAction" + )] + Customer, + #[sea_orm( + belongs_to = "super::inventory::Entity", + from = "Column::InventoryId", + to = "super::inventory::Column::InventoryId", + on_update = "NoAction", + on_delete = "NoAction" + )] + Inventory, + #[sea_orm( + belongs_to = "super::staff::Entity", + from = "Column::StaffId", + to = "super::staff::Column::StaffId", + on_update = "NoAction", + on_delete = "NoAction" + )] + Staff, + #[sea_orm(has_many = "super::payment::Entity")] + Payment, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Customer.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Inventory.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Staff.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Payment.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/staff.rs b/issues/386/src/compact/staff.rs new file mode 100644 index 00000000..805e5a26 --- /dev/null +++ b/issues/386/src/compact/staff.rs @@ -0,0 +1,76 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "staff")] +pub struct Model { + #[sea_orm( + primary_key, + auto_increment = false, + column_type = "Custom(\"BLOB\".to_owned())" + )] + pub staff_id: String, + pub first_name: String, + pub last_name: String, + pub address_id: i32, + #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())", nullable)] + pub picture: Option, + pub email: Option, + pub store_id: i32, + #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())")] + pub active: String, + pub username: String, + pub password: Option, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::address::Entity", + from = "Column::AddressId", + to = "super::address::Column::AddressId", + on_update = "Cascade", + on_delete = "NoAction" + )] + Address, + #[sea_orm( + belongs_to = "super::store::Entity", + from = "Column::StoreId", + to = "super::store::Column::StoreId", + on_update = "Cascade", + on_delete = "NoAction" + )] + Store, + #[sea_orm(has_many = "super::payment::Entity")] + Payment, + #[sea_orm(has_many = "super::rental::Entity")] + Rental, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Address.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Store.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Payment.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Rental.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/store.rs b/issues/386/src/compact/store.rs new file mode 100644 index 00000000..f7e1eb4a --- /dev/null +++ b/issues/386/src/compact/store.rs @@ -0,0 +1,64 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "store")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub store_id: i32, + #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())")] + pub manager_staff_id: String, + pub address_id: i32, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::address::Entity", + from = "Column::AddressId", + to = "super::address::Column::AddressId", + on_update = "NoAction", + on_delete = "NoAction" + )] + Address, + #[sea_orm( + belongs_to = "super::staff::Entity", + from = "Column::ManagerStaffId", + to = "super::staff::Column::StaffId", + on_update = "NoAction", + on_delete = "NoAction" + )] + Staff, + #[sea_orm(has_many = "super::customer::Entity")] + Customer, + #[sea_orm(has_many = "super::inventory::Entity")] + Inventory, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Address.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Staff.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Customer.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Inventory.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/actor.rs b/issues/386/src/expanded/actor.rs new file mode 100644 index 00000000..578d11b2 --- /dev/null +++ b/issues/386/src/expanded/actor.rs @@ -0,0 +1,73 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "actor" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub actor_id: i32, + pub first_name: String, + pub last_name: String, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + ActorId, + FirstName, + LastName, + LastUpdate, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + ActorId, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = i32; + fn auto_increment() -> bool { + true + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + FilmActor, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::ActorId => ColumnType::Integer.def(), + Self::FirstName => ColumnType::String(None).def(), + Self::LastName => ColumnType::String(None).def(), + Self::LastUpdate => ColumnType::Timestamp.def(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::FilmActor => Entity::has_many(super::film_actor::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::FilmActor.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/address.rs b/issues/386/src/expanded/address.rs new file mode 100644 index 00000000..e8b9a5b8 --- /dev/null +++ b/issues/386/src/expanded/address.rs @@ -0,0 +1,112 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "address" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub address_id: i32, + pub address: String, + pub address2: Option, + pub district: String, + pub city_id: i32, + pub postal_code: Option, + pub phone: String, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + AddressId, + Address, + Address2, + District, + CityId, + PostalCode, + Phone, + LastUpdate, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + AddressId, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = i32; + fn auto_increment() -> bool { + false + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + City, + Customer, + Staff, + Store, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::AddressId => ColumnType::Integer.def(), + Self::Address => ColumnType::String(None).def(), + Self::Address2 => ColumnType::String(None).def().null(), + Self::District => ColumnType::String(None).def(), + Self::CityId => ColumnType::Integer.def(), + Self::PostalCode => ColumnType::String(None).def().null(), + Self::Phone => ColumnType::String(None).def(), + Self::LastUpdate => ColumnType::Timestamp.def(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::City => Entity::belongs_to(super::city::Entity) + .from(Column::CityId) + .to(super::city::Column::CityId) + .into(), + Self::Customer => Entity::has_many(super::customer::Entity).into(), + Self::Staff => Entity::has_many(super::staff::Entity).into(), + Self::Store => Entity::has_many(super::store::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::City.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Customer.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Staff.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Store.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/category.rs b/issues/386/src/expanded/category.rs new file mode 100644 index 00000000..4ce53b6a --- /dev/null +++ b/issues/386/src/expanded/category.rs @@ -0,0 +1,70 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "category" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub category_id: String, + pub name: String, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + CategoryId, + Name, + LastUpdate, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + CategoryId, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = String; + fn auto_increment() -> bool { + false + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + FilmCategory, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::CategoryId => ColumnType::Custom("BLOB".to_owned()).def(), + Self::Name => ColumnType::String(None).def(), + Self::LastUpdate => ColumnType::Timestamp.def(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::FilmCategory => Entity::has_many(super::film_category::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::FilmCategory.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/city.rs b/issues/386/src/expanded/city.rs new file mode 100644 index 00000000..eb4010d2 --- /dev/null +++ b/issues/386/src/expanded/city.rs @@ -0,0 +1,84 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "city" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub city_id: i32, + pub city: String, + pub country_id: String, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + CityId, + City, + CountryId, + LastUpdate, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + CityId, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = i32; + fn auto_increment() -> bool { + false + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Country, + Address, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::CityId => ColumnType::Integer.def(), + Self::City => ColumnType::String(None).def(), + Self::CountryId => ColumnType::Custom("BLOB".to_owned()).def(), + Self::LastUpdate => ColumnType::Timestamp.def(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Country => Entity::belongs_to(super::country::Entity) + .from(Column::CountryId) + .to(super::country::Column::CountryId) + .into(), + Self::Address => Entity::has_many(super::address::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Country.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Address.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/country.rs b/issues/386/src/expanded/country.rs new file mode 100644 index 00000000..5901ccbc --- /dev/null +++ b/issues/386/src/expanded/country.rs @@ -0,0 +1,70 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "country" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub country_id: String, + pub country: String, + pub last_update: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + CountryId, + Country, + LastUpdate, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + CountryId, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = String; + fn auto_increment() -> bool { + false + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + City, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::CountryId => ColumnType::Custom("BLOB".to_owned()).def(), + Self::Country => ColumnType::String(None).def(), + Self::LastUpdate => ColumnType::Timestamp.def().null(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::City => Entity::has_many(super::city::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::City.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/customer.rs b/issues/386/src/expanded/customer.rs new file mode 100644 index 00000000..1adbaa66 --- /dev/null +++ b/issues/386/src/expanded/customer.rs @@ -0,0 +1,118 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "customer" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub customer_id: i32, + pub store_id: i32, + pub first_name: String, + pub last_name: String, + pub email: Option, + pub address_id: i32, + pub active: String, + pub create_date: DateTime, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + CustomerId, + StoreId, + FirstName, + LastName, + Email, + AddressId, + Active, + CreateDate, + LastUpdate, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + CustomerId, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = i32; + fn auto_increment() -> bool { + false + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Address, + Store, + Payment, + Rental, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::CustomerId => ColumnType::Integer.def(), + Self::StoreId => ColumnType::Integer.def(), + Self::FirstName => ColumnType::String(None).def(), + Self::LastName => ColumnType::String(None).def(), + Self::Email => ColumnType::String(None).def().null(), + Self::AddressId => ColumnType::Integer.def(), + Self::Active => ColumnType::Custom("BLOB".to_owned()).def(), + Self::CreateDate => ColumnType::Timestamp.def(), + Self::LastUpdate => ColumnType::Timestamp.def(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Address => Entity::belongs_to(super::address::Entity) + .from(Column::AddressId) + .to(super::address::Column::AddressId) + .into(), + Self::Store => Entity::belongs_to(super::store::Entity) + .from(Column::StoreId) + .to(super::store::Column::StoreId) + .into(), + Self::Payment => Entity::has_many(super::payment::Entity).into(), + Self::Rental => Entity::has_many(super::rental::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Address.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Store.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Payment.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Rental.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/film.rs b/issues/386/src/expanded/film.rs new file mode 100644 index 00000000..b4e12ce3 --- /dev/null +++ b/issues/386/src/expanded/film.rs @@ -0,0 +1,126 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "film" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub film_id: i32, + pub title: String, + pub description: Option, + pub release_year: Option, + pub language_id: String, + pub original_language_id: Option, + pub rental_duration: String, + pub rental_rate: Decimal, + pub length: Option, + pub replacement_cost: Decimal, + pub rating: Option, + pub special_features: Option, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + FilmId, + Title, + Description, + ReleaseYear, + LanguageId, + OriginalLanguageId, + RentalDuration, + RentalRate, + Length, + ReplacementCost, + Rating, + SpecialFeatures, + LastUpdate, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + FilmId, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = i32; + fn auto_increment() -> bool { + false + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Language2, + Language1, + FilmActor, + FilmCategory, + Inventory, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::FilmId => ColumnType::Integer.def(), + Self::Title => ColumnType::String(None).def(), + Self::Description => ColumnType::Custom("BLOB".to_owned()).def().null(), + Self::ReleaseYear => ColumnType::String(None).def().null(), + Self::LanguageId => ColumnType::Custom("BLOB".to_owned()).def(), + Self::OriginalLanguageId => ColumnType::Custom("BLOB".to_owned()).def().null(), + Self::RentalDuration => ColumnType::Custom("BLOB".to_owned()).def(), + Self::RentalRate => ColumnType::Decimal(Some((4u32, 2u32))).def(), + Self::Length => ColumnType::Custom("BLOB".to_owned()).def().null(), + Self::ReplacementCost => ColumnType::Decimal(Some((5u32, 2u32))).def(), + Self::Rating => ColumnType::String(None).def().null(), + Self::SpecialFeatures => ColumnType::String(None).def().null(), + Self::LastUpdate => ColumnType::Timestamp.def(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Language2 => Entity::belongs_to(super::language::Entity) + .from(Column::OriginalLanguageId) + .to(super::language::Column::LanguageId) + .into(), + Self::Language1 => Entity::belongs_to(super::language::Entity) + .from(Column::LanguageId) + .to(super::language::Column::LanguageId) + .into(), + Self::FilmActor => Entity::has_many(super::film_actor::Entity).into(), + Self::FilmCategory => Entity::has_many(super::film_category::Entity).into(), + Self::Inventory => Entity::has_many(super::inventory::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::FilmActor.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::FilmCategory.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Inventory.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/film_actor.rs b/issues/386/src/expanded/film_actor.rs new file mode 100644 index 00000000..86211cec --- /dev/null +++ b/issues/386/src/expanded/film_actor.rs @@ -0,0 +1,85 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "film_actor" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub actor_id: i32, + pub film_id: i32, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + ActorId, + FilmId, + LastUpdate, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + ActorId, + FilmId, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = (i32, i32); + fn auto_increment() -> bool { + false + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Film, + Actor, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::ActorId => ColumnType::Integer.def(), + Self::FilmId => ColumnType::Integer.def(), + Self::LastUpdate => ColumnType::Timestamp.def(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Film => Entity::belongs_to(super::film::Entity) + .from(Column::FilmId) + .to(super::film::Column::FilmId) + .into(), + Self::Actor => Entity::belongs_to(super::actor::Entity) + .from(Column::ActorId) + .to(super::actor::Column::ActorId) + .into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Film.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Actor.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/film_category.rs b/issues/386/src/expanded/film_category.rs new file mode 100644 index 00000000..c1cc118a --- /dev/null +++ b/issues/386/src/expanded/film_category.rs @@ -0,0 +1,85 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "film_category" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub film_id: i32, + pub category_id: String, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + FilmId, + CategoryId, + LastUpdate, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + FilmId, + CategoryId, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = (i32, String); + fn auto_increment() -> bool { + false + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Category, + Film, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::FilmId => ColumnType::Integer.def(), + Self::CategoryId => ColumnType::Custom("BLOB".to_owned()).def(), + Self::LastUpdate => ColumnType::Timestamp.def(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Category => Entity::belongs_to(super::category::Entity) + .from(Column::CategoryId) + .to(super::category::Column::CategoryId) + .into(), + Self::Film => Entity::belongs_to(super::film::Entity) + .from(Column::FilmId) + .to(super::film::Column::FilmId) + .into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Category.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Film.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/film_text.rs b/issues/386/src/expanded/film_text.rs new file mode 100644 index 00000000..87dbeda4 --- /dev/null +++ b/issues/386/src/expanded/film_text.rs @@ -0,0 +1,60 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "film_text" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub film_id: String, + pub title: String, + pub description: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + FilmId, + Title, + Description, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + FilmId, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = String; + fn auto_increment() -> bool { + false + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation {} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::FilmId => ColumnType::Custom("BLOB".to_owned()).def(), + Self::Title => ColumnType::String(None).def(), + Self::Description => ColumnType::Custom("BLOB".to_owned()).def().null(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + panic!("No RelationDef") + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/inventory.rs b/issues/386/src/expanded/inventory.rs new file mode 100644 index 00000000..dbbb412b --- /dev/null +++ b/issues/386/src/expanded/inventory.rs @@ -0,0 +1,95 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "inventory" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub inventory_id: i32, + pub film_id: i32, + pub store_id: i32, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + InventoryId, + FilmId, + StoreId, + LastUpdate, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + InventoryId, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = i32; + fn auto_increment() -> bool { + false + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Film, + Store, + Rental, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::InventoryId => ColumnType::Integer.def(), + Self::FilmId => ColumnType::Integer.def(), + Self::StoreId => ColumnType::Integer.def(), + Self::LastUpdate => ColumnType::Timestamp.def(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Film => Entity::belongs_to(super::film::Entity) + .from(Column::FilmId) + .to(super::film::Column::FilmId) + .into(), + Self::Store => Entity::belongs_to(super::store::Entity) + .from(Column::StoreId) + .to(super::store::Column::StoreId) + .into(), + Self::Rental => Entity::has_many(super::rental::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Film.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Store.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Rental.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/language.rs b/issues/386/src/expanded/language.rs new file mode 100644 index 00000000..cffd118e --- /dev/null +++ b/issues/386/src/expanded/language.rs @@ -0,0 +1,60 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "language" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub language_id: String, + pub name: String, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + LanguageId, + Name, + LastUpdate, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + LanguageId, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = String; + fn auto_increment() -> bool { + false + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation {} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::LanguageId => ColumnType::Custom("BLOB".to_owned()).def(), + Self::Name => ColumnType::Custom("BLOB".to_owned()).def(), + Self::LastUpdate => ColumnType::Timestamp.def(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + panic!("No RelationDef") + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/mod.rs b/issues/386/src/expanded/mod.rs new file mode 100644 index 00000000..d7f098fc --- /dev/null +++ b/issues/386/src/expanded/mod.rs @@ -0,0 +1,20 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +pub mod prelude; + +pub mod actor; +pub mod address; +pub mod category; +pub mod city; +pub mod country; +pub mod customer; +pub mod film; +pub mod film_actor; +pub mod film_category; +pub mod film_text; +pub mod inventory; +pub mod language; +pub mod payment; +pub mod rental; +pub mod staff; +pub mod store; diff --git a/issues/386/src/expanded/payment.rs b/issues/386/src/expanded/payment.rs new file mode 100644 index 00000000..7977464b --- /dev/null +++ b/issues/386/src/expanded/payment.rs @@ -0,0 +1,107 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "payment" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub payment_id: i32, + pub customer_id: i32, + pub staff_id: String, + pub rental_id: Option, + pub amount: Decimal, + pub payment_date: DateTime, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + PaymentId, + CustomerId, + StaffId, + RentalId, + Amount, + PaymentDate, + LastUpdate, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + PaymentId, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = i32; + fn auto_increment() -> bool { + false + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Staff, + Customer, + Rental, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::PaymentId => ColumnType::Integer.def(), + Self::CustomerId => ColumnType::Integer.def(), + Self::StaffId => ColumnType::Custom("BLOB".to_owned()).def(), + Self::RentalId => ColumnType::Integer.def().null(), + Self::Amount => ColumnType::Decimal(Some((5u32, 2u32))).def(), + Self::PaymentDate => ColumnType::Timestamp.def(), + Self::LastUpdate => ColumnType::Timestamp.def(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Staff => Entity::belongs_to(super::staff::Entity) + .from(Column::StaffId) + .to(super::staff::Column::StaffId) + .into(), + Self::Customer => Entity::belongs_to(super::customer::Entity) + .from(Column::CustomerId) + .to(super::customer::Column::CustomerId) + .into(), + Self::Rental => Entity::belongs_to(super::rental::Entity) + .from(Column::RentalId) + .to(super::rental::Column::RentalId) + .into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Staff.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Customer.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Rental.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/prelude.rs b/issues/386/src/expanded/prelude.rs new file mode 100644 index 00000000..85cecd87 --- /dev/null +++ b/issues/386/src/expanded/prelude.rs @@ -0,0 +1,18 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +pub use super::actor::Entity as Actor; +pub use super::address::Entity as Address; +pub use super::category::Entity as Category; +pub use super::city::Entity as City; +pub use super::country::Entity as Country; +pub use super::customer::Entity as Customer; +pub use super::film::Entity as Film; +pub use super::film_actor::Entity as FilmActor; +pub use super::film_category::Entity as FilmCategory; +pub use super::film_text::Entity as FilmText; +pub use super::inventory::Entity as Inventory; +pub use super::language::Entity as Language; +pub use super::payment::Entity as Payment; +pub use super::rental::Entity as Rental; +pub use super::staff::Entity as Staff; +pub use super::store::Entity as Store; diff --git a/issues/386/src/expanded/rental.rs b/issues/386/src/expanded/rental.rs new file mode 100644 index 00000000..952a0285 --- /dev/null +++ b/issues/386/src/expanded/rental.rs @@ -0,0 +1,115 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "rental" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub rental_id: i32, + pub rental_date: DateTime, + pub inventory_id: i32, + pub customer_id: i32, + pub return_date: Option, + pub staff_id: String, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + RentalId, + RentalDate, + InventoryId, + CustomerId, + ReturnDate, + StaffId, + LastUpdate, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + RentalId, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = i32; + fn auto_increment() -> bool { + false + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Customer, + Inventory, + Staff, + Payment, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::RentalId => ColumnType::Integer.def(), + Self::RentalDate => ColumnType::Timestamp.def(), + Self::InventoryId => ColumnType::Integer.def(), + Self::CustomerId => ColumnType::Integer.def(), + Self::ReturnDate => ColumnType::Timestamp.def().null(), + Self::StaffId => ColumnType::Custom("BLOB".to_owned()).def(), + Self::LastUpdate => ColumnType::Timestamp.def(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Customer => Entity::belongs_to(super::customer::Entity) + .from(Column::CustomerId) + .to(super::customer::Column::CustomerId) + .into(), + Self::Inventory => Entity::belongs_to(super::inventory::Entity) + .from(Column::InventoryId) + .to(super::inventory::Column::InventoryId) + .into(), + Self::Staff => Entity::belongs_to(super::staff::Entity) + .from(Column::StaffId) + .to(super::staff::Column::StaffId) + .into(), + Self::Payment => Entity::has_many(super::payment::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Customer.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Inventory.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Staff.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Payment.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/staff.rs b/issues/386/src/expanded/staff.rs new file mode 100644 index 00000000..a24721cf --- /dev/null +++ b/issues/386/src/expanded/staff.rs @@ -0,0 +1,124 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "staff" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub staff_id: String, + pub first_name: String, + pub last_name: String, + pub address_id: i32, + pub picture: Option, + pub email: Option, + pub store_id: i32, + pub active: String, + pub username: String, + pub password: Option, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + StaffId, + FirstName, + LastName, + AddressId, + Picture, + Email, + StoreId, + Active, + Username, + Password, + LastUpdate, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + StaffId, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = String; + fn auto_increment() -> bool { + false + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Address, + Store, + Payment, + Rental, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::StaffId => ColumnType::Custom("BLOB".to_owned()).def(), + Self::FirstName => ColumnType::String(None).def(), + Self::LastName => ColumnType::String(None).def(), + Self::AddressId => ColumnType::Integer.def(), + Self::Picture => ColumnType::Custom("BLOB".to_owned()).def().null(), + Self::Email => ColumnType::String(None).def().null(), + Self::StoreId => ColumnType::Integer.def(), + Self::Active => ColumnType::Custom("BLOB".to_owned()).def(), + Self::Username => ColumnType::String(None).def(), + Self::Password => ColumnType::String(None).def().null(), + Self::LastUpdate => ColumnType::Timestamp.def(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Address => Entity::belongs_to(super::address::Entity) + .from(Column::AddressId) + .to(super::address::Column::AddressId) + .into(), + Self::Store => Entity::belongs_to(super::store::Entity) + .from(Column::StoreId) + .to(super::store::Column::StoreId) + .into(), + Self::Payment => Entity::has_many(super::payment::Entity).into(), + Self::Rental => Entity::has_many(super::rental::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Address.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Store.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Payment.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Rental.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/store.rs b/issues/386/src/expanded/store.rs new file mode 100644 index 00000000..1d04fd66 --- /dev/null +++ b/issues/386/src/expanded/store.rs @@ -0,0 +1,103 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "store" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub store_id: i32, + pub manager_staff_id: String, + pub address_id: i32, + pub last_update: DateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + StoreId, + ManagerStaffId, + AddressId, + LastUpdate, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + StoreId, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = i32; + fn auto_increment() -> bool { + false + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Address, + Staff, + Customer, + Inventory, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::StoreId => ColumnType::Integer.def(), + Self::ManagerStaffId => ColumnType::Custom("BLOB".to_owned()).def(), + Self::AddressId => ColumnType::Integer.def(), + Self::LastUpdate => ColumnType::Timestamp.def(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Address => Entity::belongs_to(super::address::Entity) + .from(Column::AddressId) + .to(super::address::Column::AddressId) + .into(), + Self::Staff => Entity::belongs_to(super::staff::Entity) + .from(Column::ManagerStaffId) + .to(super::staff::Column::StaffId) + .into(), + Self::Customer => Entity::has_many(super::customer::Entity).into(), + Self::Inventory => Entity::has_many(super::inventory::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Address.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Staff.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Customer.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Inventory.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/main.rs b/issues/386/src/main.rs new file mode 100644 index 00000000..c76f4650 --- /dev/null +++ b/issues/386/src/main.rs @@ -0,0 +1,4 @@ +mod compact; +mod expanded; + +pub fn main() {} diff --git a/sea-orm-cli/Cargo.toml b/sea-orm-cli/Cargo.toml index 6dca13bb..8495cc5b 100644 --- a/sea-orm-cli/Cargo.toml +++ b/sea-orm-cli/Cargo.toml @@ -22,9 +22,10 @@ clap = { version = "^2.33.3" } dotenv = { version = "^0.15" } async-std = { version = "^1.9", features = [ "attributes" ] } sea-orm-codegen = { version = "^0.4.2", path = "../sea-orm-codegen" } -sea-schema = { version = "0.3.0", default-features = false, features = [ +sea-schema = { version = "0.3.0", git = "https://github.com/SeaQL/sea-schema.git", branch = "sqlite-codegen", default-features = false, features = [ "debug-print", "sqlx-mysql", + "sqlx-sqlite", "sqlx-postgres", "discovery", "writer", diff --git a/sea-orm-cli/README.md b/sea-orm-cli/README.md index 531a3c46..bcf49100 100644 --- a/sea-orm-cli/README.md +++ b/sea-orm-cli/README.md @@ -9,9 +9,12 @@ cargo run -- -h Running Entity Generator: ```sh -# MySQL (`--database-schema` option is ignored) +# MySQL (`--database-schema` option is ignored) cargo run -- generate entity -u mysql://sea:sea@localhost/bakery -o out +# SQLite (`--database-schema` option is ignored) +cargo run -- generate entity -u sqlite://bakery.db -o out + # PostgreSQL cargo run -- generate entity -u postgres://sea:sea@localhost/bakery -s public -o out ``` diff --git a/sea-orm-cli/src/main.rs b/sea-orm-cli/src/main.rs index aee80b0b..f689a52e 100644 --- a/sea-orm-cli/src/main.rs +++ b/sea-orm-cli/src/main.rs @@ -53,39 +53,20 @@ async fn run_generate_command(matches: &ArgMatches<'_>) -> Result<(), Box) -> Result<(), Box { use sea_schema::mysql::discovery::SchemaDiscovery; @@ -120,6 +131,21 @@ async fn run_generate_command(matches: &ArgMatches<'_>) -> Result<(), Box { + use sea_schema::sqlite::SchemaDiscovery; + use sqlx::SqlitePool; + + let connection = SqlitePool::connect(url.as_str()).await?; + let schema_discovery = SchemaDiscovery::new(connection); + let schema = schema_discovery.discover().await?; + schema + .tables + .into_iter() + .filter(|schema| filter_tables(&schema.name)) + .filter(|schema| filter_hidden_tables(&schema.name)) + .map(|schema| schema.write()) + .collect() + } "postgres" | "postgresql" => { use sea_schema::postgres::discovery::SchemaDiscovery; use sqlx::PgPool; diff --git a/sea-orm-codegen/src/entity/transformer.rs b/sea-orm-codegen/src/entity/transformer.rs index 8c9cdd1c..d526c98c 100644 --- a/sea-orm-codegen/src/entity/transformer.rs +++ b/sea-orm-codegen/src/entity/transformer.rs @@ -2,27 +2,19 @@ use crate::{ ActiveEnum, Column, ConjunctRelation, Entity, EntityWriter, Error, PrimaryKey, Relation, RelationType, }; -use sea_query::TableStatement; +use sea_query::{ColumnSpec, TableCreateStatement}; use std::collections::HashMap; #[derive(Clone, Debug)] pub struct EntityTransformer; impl EntityTransformer { - pub fn transform(table_stmts: Vec) -> Result { + pub fn transform(table_create_stmts: Vec) -> Result { let mut enums: HashMap = HashMap::new(); let mut inverse_relations: HashMap> = HashMap::new(); let mut conjunct_relations: HashMap> = HashMap::new(); let mut entities = HashMap::new(); - for table_stmt in table_stmts.into_iter() { - let table_create = match table_stmt { - TableStatement::Create(stmt) => stmt, - _ => { - return Err(Error::TransformError( - "TableStatement should be create".into(), - )) - } - }; + for table_create in table_create_stmts.into_iter() { let table_name = match table_create.get_table_name() { Some(table_ref) => match table_ref { sea_query::TableRef::Table(t) @@ -39,10 +31,22 @@ impl EntityTransformer { )) } }; + let mut primary_keys: Vec = Vec::new(); let columns: Vec = table_create .get_columns() .iter() - .map(|col_def| col_def.into()) + .map(|col_def| { + let primary_key = col_def + .get_column_spec() + .iter() + .any(|spec| matches!(spec, ColumnSpec::PrimaryKey)); + if primary_key { + primary_keys.push(PrimaryKey { + name: col_def.get_column_name(), + }); + } + col_def.into() + }) .map(|mut col: Column| { col.unique = table_create .get_indexes() @@ -99,20 +103,21 @@ impl EntityTransformer { }) .rev() .collect(); - let primary_keys = table_create - .get_indexes() - .iter() - .filter(|index| index.is_primary_key()) - .map(|index| { - index - .get_index_spec() - .get_column_names() - .into_iter() - .map(|name| PrimaryKey { name }) - .collect::>() - }) - .flatten() - .collect(); + primary_keys.extend( + table_create + .get_indexes() + .iter() + .filter(|index| index.is_primary_key()) + .map(|index| { + index + .get_index_spec() + .get_column_names() + .into_iter() + .map(|name| PrimaryKey { name }) + .collect::>() + }) + .flatten(), + ); let entity = Entity { table_name: table_name.clone(), columns, @@ -180,9 +185,17 @@ impl EntityTransformer { } } } - for (tbl_name, mut relations) in inverse_relations.into_iter() { + for (tbl_name, relations) in inverse_relations.into_iter() { if let Some(entity) = entities.get_mut(&tbl_name) { - entity.relations.append(&mut relations); + for relation in relations.into_iter() { + let duplicate_relation = entity + .relations + .iter() + .any(|rel| rel.ref_table == relation.ref_table); + if !duplicate_relation { + entity.relations.push(relation); + } + } } } for (tbl_name, mut conjunct_relations) in conjunct_relations.into_iter() { From 2bc58639776240e502eb57da5f46c3e05515aab7 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sat, 25 Dec 2021 11:33:21 +0800 Subject: [PATCH 35/36] Remove issues/386 --- .github/workflows/rust.yml | 2 +- issues/386/Cargo.toml | 11 -- issues/386/src/compact/actor.rs | 27 ----- issues/386/src/compact/address.rs | 61 ----------- issues/386/src/compact/category.rs | 30 ------ issues/386/src/compact/city.rs | 42 -------- issues/386/src/compact/country.rs | 30 ------ issues/386/src/compact/customer.rs | 69 ------------- issues/386/src/compact/film.rs | 75 -------------- issues/386/src/compact/film_actor.rs | 47 --------- issues/386/src/compact/film_category.rs | 51 --------- issues/386/src/compact/film_text.rs | 28 ----- issues/386/src/compact/inventory.rs | 55 ---------- issues/386/src/compact/language.rs | 28 ----- issues/386/src/compact/mod.rs | 20 ---- issues/386/src/compact/payment.rs | 66 ------------ issues/386/src/compact/prelude.rs | 18 ---- issues/386/src/compact/rental.rs | 73 ------------- issues/386/src/compact/staff.rs | 76 -------------- issues/386/src/compact/store.rs | 64 ------------ issues/386/src/expanded/actor.rs | 73 ------------- issues/386/src/expanded/address.rs | 112 -------------------- issues/386/src/expanded/category.rs | 70 ------------- issues/386/src/expanded/city.rs | 84 --------------- issues/386/src/expanded/country.rs | 70 ------------- issues/386/src/expanded/customer.rs | 118 --------------------- issues/386/src/expanded/film.rs | 126 ----------------------- issues/386/src/expanded/film_actor.rs | 85 --------------- issues/386/src/expanded/film_category.rs | 85 --------------- issues/386/src/expanded/film_text.rs | 60 ----------- issues/386/src/expanded/inventory.rs | 95 ----------------- issues/386/src/expanded/language.rs | 60 ----------- issues/386/src/expanded/mod.rs | 20 ---- issues/386/src/expanded/payment.rs | 107 ------------------- issues/386/src/expanded/prelude.rs | 18 ---- issues/386/src/expanded/rental.rs | 115 --------------------- issues/386/src/expanded/staff.rs | 124 ---------------------- issues/386/src/expanded/store.rs | 103 ------------------ issues/386/src/main.rs | 4 - 39 files changed, 1 insertion(+), 2401 deletions(-) delete mode 100644 issues/386/Cargo.toml delete mode 100644 issues/386/src/compact/actor.rs delete mode 100644 issues/386/src/compact/address.rs delete mode 100644 issues/386/src/compact/category.rs delete mode 100644 issues/386/src/compact/city.rs delete mode 100644 issues/386/src/compact/country.rs delete mode 100644 issues/386/src/compact/customer.rs delete mode 100644 issues/386/src/compact/film.rs delete mode 100644 issues/386/src/compact/film_actor.rs delete mode 100644 issues/386/src/compact/film_category.rs delete mode 100644 issues/386/src/compact/film_text.rs delete mode 100644 issues/386/src/compact/inventory.rs delete mode 100644 issues/386/src/compact/language.rs delete mode 100644 issues/386/src/compact/mod.rs delete mode 100644 issues/386/src/compact/payment.rs delete mode 100644 issues/386/src/compact/prelude.rs delete mode 100644 issues/386/src/compact/rental.rs delete mode 100644 issues/386/src/compact/staff.rs delete mode 100644 issues/386/src/compact/store.rs delete mode 100644 issues/386/src/expanded/actor.rs delete mode 100644 issues/386/src/expanded/address.rs delete mode 100644 issues/386/src/expanded/category.rs delete mode 100644 issues/386/src/expanded/city.rs delete mode 100644 issues/386/src/expanded/country.rs delete mode 100644 issues/386/src/expanded/customer.rs delete mode 100644 issues/386/src/expanded/film.rs delete mode 100644 issues/386/src/expanded/film_actor.rs delete mode 100644 issues/386/src/expanded/film_category.rs delete mode 100644 issues/386/src/expanded/film_text.rs delete mode 100644 issues/386/src/expanded/inventory.rs delete mode 100644 issues/386/src/expanded/language.rs delete mode 100644 issues/386/src/expanded/mod.rs delete mode 100644 issues/386/src/expanded/payment.rs delete mode 100644 issues/386/src/expanded/prelude.rs delete mode 100644 issues/386/src/expanded/rental.rs delete mode 100644 issues/386/src/expanded/staff.rs delete mode 100644 issues/386/src/expanded/store.rs delete mode 100644 issues/386/src/main.rs diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index b9618904..4affff66 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -316,7 +316,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - path: [86, 249, 262, 319, 324, 352, 356, 386] + path: [86, 249, 262, 319, 324, 352, 356] steps: - uses: actions/checkout@v2 diff --git a/issues/386/Cargo.toml b/issues/386/Cargo.toml deleted file mode 100644 index f3a975f1..00000000 --- a/issues/386/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[workspace] -# A separate workspace - -[package] -name = "sea-orm-issues-386" -version = "0.1.0" -edition = "2021" -publish = false - -[dependencies] -sea-orm = { path = "../../", features = [ "sqlx-mysql", "runtime-async-std-native-tls" ]} diff --git a/issues/386/src/compact/actor.rs b/issues/386/src/compact/actor.rs deleted file mode 100644 index ad7248d6..00000000 --- a/issues/386/src/compact/actor.rs +++ /dev/null @@ -1,27 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "actor")] -pub struct Model { - #[sea_orm(primary_key)] - pub actor_id: i32, - pub first_name: String, - pub last_name: String, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm(has_many = "super::film_actor::Entity")] - FilmActor, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::FilmActor.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/address.rs b/issues/386/src/compact/address.rs deleted file mode 100644 index 04541e3c..00000000 --- a/issues/386/src/compact/address.rs +++ /dev/null @@ -1,61 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "address")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub address_id: i32, - pub address: String, - pub address2: Option, - pub district: String, - pub city_id: i32, - pub postal_code: Option, - pub phone: String, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::city::Entity", - from = "Column::CityId", - to = "super::city::Column::CityId", - on_update = "Cascade", - on_delete = "NoAction" - )] - City, - #[sea_orm(has_many = "super::customer::Entity")] - Customer, - #[sea_orm(has_many = "super::staff::Entity")] - Staff, - #[sea_orm(has_many = "super::store::Entity")] - Store, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::City.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Customer.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Staff.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Store.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/category.rs b/issues/386/src/compact/category.rs deleted file mode 100644 index a7ff20f3..00000000 --- a/issues/386/src/compact/category.rs +++ /dev/null @@ -1,30 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "category")] -pub struct Model { - #[sea_orm( - primary_key, - auto_increment = false, - column_type = "Custom(\"BLOB\".to_owned())" - )] - pub category_id: String, - pub name: String, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm(has_many = "super::film_category::Entity")] - FilmCategory, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::FilmCategory.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/city.rs b/issues/386/src/compact/city.rs deleted file mode 100644 index 02d28b0d..00000000 --- a/issues/386/src/compact/city.rs +++ /dev/null @@ -1,42 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "city")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub city_id: i32, - pub city: String, - #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())")] - pub country_id: String, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::country::Entity", - from = "Column::CountryId", - to = "super::country::Column::CountryId", - on_update = "Cascade", - on_delete = "NoAction" - )] - Country, - #[sea_orm(has_many = "super::address::Entity")] - Address, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Country.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Address.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/country.rs b/issues/386/src/compact/country.rs deleted file mode 100644 index 9fe96829..00000000 --- a/issues/386/src/compact/country.rs +++ /dev/null @@ -1,30 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "country")] -pub struct Model { - #[sea_orm( - primary_key, - auto_increment = false, - column_type = "Custom(\"BLOB\".to_owned())" - )] - pub country_id: String, - pub country: String, - pub last_update: Option, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm(has_many = "super::city::Entity")] - City, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::City.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/customer.rs b/issues/386/src/compact/customer.rs deleted file mode 100644 index 95807b65..00000000 --- a/issues/386/src/compact/customer.rs +++ /dev/null @@ -1,69 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "customer")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub customer_id: i32, - pub store_id: i32, - pub first_name: String, - pub last_name: String, - pub email: Option, - pub address_id: i32, - #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())")] - pub active: String, - pub create_date: DateTime, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::address::Entity", - from = "Column::AddressId", - to = "super::address::Column::AddressId", - on_update = "Cascade", - on_delete = "NoAction" - )] - Address, - #[sea_orm( - belongs_to = "super::store::Entity", - from = "Column::StoreId", - to = "super::store::Column::StoreId", - on_update = "Cascade", - on_delete = "NoAction" - )] - Store, - #[sea_orm(has_many = "super::payment::Entity")] - Payment, - #[sea_orm(has_many = "super::rental::Entity")] - Rental, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Address.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Store.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Payment.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Rental.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/film.rs b/issues/386/src/compact/film.rs deleted file mode 100644 index 39cf0330..00000000 --- a/issues/386/src/compact/film.rs +++ /dev/null @@ -1,75 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "film")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub film_id: i32, - pub title: String, - #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())", nullable)] - pub description: Option, - pub release_year: Option, - #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())")] - pub language_id: String, - #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())", nullable)] - pub original_language_id: Option, - #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())")] - pub rental_duration: String, - #[sea_orm(column_type = "Decimal(Some((4, 2)))")] - pub rental_rate: Decimal, - #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())", nullable)] - pub length: Option, - #[sea_orm(column_type = "Decimal(Some((5, 2)))")] - pub replacement_cost: Decimal, - pub rating: Option, - pub special_features: Option, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::language::Entity", - from = "Column::OriginalLanguageId", - to = "super::language::Column::LanguageId", - on_update = "NoAction", - on_delete = "NoAction" - )] - Language2, - #[sea_orm( - belongs_to = "super::language::Entity", - from = "Column::LanguageId", - to = "super::language::Column::LanguageId", - on_update = "NoAction", - on_delete = "NoAction" - )] - Language1, - #[sea_orm(has_many = "super::film_actor::Entity")] - FilmActor, - #[sea_orm(has_many = "super::film_category::Entity")] - FilmCategory, - #[sea_orm(has_many = "super::inventory::Entity")] - Inventory, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::FilmActor.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::FilmCategory.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Inventory.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/film_actor.rs b/issues/386/src/compact/film_actor.rs deleted file mode 100644 index ba23ccb7..00000000 --- a/issues/386/src/compact/film_actor.rs +++ /dev/null @@ -1,47 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "film_actor")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub actor_id: i32, - #[sea_orm(primary_key, auto_increment = false)] - pub film_id: i32, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::film::Entity", - from = "Column::FilmId", - to = "super::film::Column::FilmId", - on_update = "Cascade", - on_delete = "NoAction" - )] - Film, - #[sea_orm( - belongs_to = "super::actor::Entity", - from = "Column::ActorId", - to = "super::actor::Column::ActorId", - on_update = "Cascade", - on_delete = "NoAction" - )] - Actor, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Film.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Actor.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/film_category.rs b/issues/386/src/compact/film_category.rs deleted file mode 100644 index 222a773a..00000000 --- a/issues/386/src/compact/film_category.rs +++ /dev/null @@ -1,51 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "film_category")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub film_id: i32, - #[sea_orm( - primary_key, - auto_increment = false, - column_type = "Custom(\"BLOB\".to_owned())" - )] - pub category_id: String, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::category::Entity", - from = "Column::CategoryId", - to = "super::category::Column::CategoryId", - on_update = "Cascade", - on_delete = "NoAction" - )] - Category, - #[sea_orm( - belongs_to = "super::film::Entity", - from = "Column::FilmId", - to = "super::film::Column::FilmId", - on_update = "Cascade", - on_delete = "NoAction" - )] - Film, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Category.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Film.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/film_text.rs b/issues/386/src/compact/film_text.rs deleted file mode 100644 index d8f26b69..00000000 --- a/issues/386/src/compact/film_text.rs +++ /dev/null @@ -1,28 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "film_text")] -pub struct Model { - #[sea_orm( - primary_key, - auto_increment = false, - column_type = "Custom(\"BLOB\".to_owned())" - )] - pub film_id: String, - pub title: String, - #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())", nullable)] - pub description: Option, -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation {} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - panic!("No RelationDef") - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/inventory.rs b/issues/386/src/compact/inventory.rs deleted file mode 100644 index 2f71f5c4..00000000 --- a/issues/386/src/compact/inventory.rs +++ /dev/null @@ -1,55 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "inventory")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub inventory_id: i32, - pub film_id: i32, - pub store_id: i32, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::film::Entity", - from = "Column::FilmId", - to = "super::film::Column::FilmId", - on_update = "Cascade", - on_delete = "NoAction" - )] - Film, - #[sea_orm( - belongs_to = "super::store::Entity", - from = "Column::StoreId", - to = "super::store::Column::StoreId", - on_update = "Cascade", - on_delete = "NoAction" - )] - Store, - #[sea_orm(has_many = "super::rental::Entity")] - Rental, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Film.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Store.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Rental.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/language.rs b/issues/386/src/compact/language.rs deleted file mode 100644 index d77db368..00000000 --- a/issues/386/src/compact/language.rs +++ /dev/null @@ -1,28 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "language")] -pub struct Model { - #[sea_orm( - primary_key, - auto_increment = false, - column_type = "Custom(\"BLOB\".to_owned())" - )] - pub language_id: String, - #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())")] - pub name: String, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation {} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - panic!("No RelationDef") - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/mod.rs b/issues/386/src/compact/mod.rs deleted file mode 100644 index d7f098fc..00000000 --- a/issues/386/src/compact/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -pub mod prelude; - -pub mod actor; -pub mod address; -pub mod category; -pub mod city; -pub mod country; -pub mod customer; -pub mod film; -pub mod film_actor; -pub mod film_category; -pub mod film_text; -pub mod inventory; -pub mod language; -pub mod payment; -pub mod rental; -pub mod staff; -pub mod store; diff --git a/issues/386/src/compact/payment.rs b/issues/386/src/compact/payment.rs deleted file mode 100644 index 43c494b4..00000000 --- a/issues/386/src/compact/payment.rs +++ /dev/null @@ -1,66 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "payment")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub payment_id: i32, - pub customer_id: i32, - #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())")] - pub staff_id: String, - pub rental_id: Option, - #[sea_orm(column_type = "Decimal(Some((5, 2)))")] - pub amount: Decimal, - pub payment_date: DateTime, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::staff::Entity", - from = "Column::StaffId", - to = "super::staff::Column::StaffId", - on_update = "NoAction", - on_delete = "NoAction" - )] - Staff, - #[sea_orm( - belongs_to = "super::customer::Entity", - from = "Column::CustomerId", - to = "super::customer::Column::CustomerId", - on_update = "NoAction", - on_delete = "NoAction" - )] - Customer, - #[sea_orm( - belongs_to = "super::rental::Entity", - from = "Column::RentalId", - to = "super::rental::Column::RentalId", - on_update = "Cascade", - on_delete = "SetNull" - )] - Rental, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Staff.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Customer.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Rental.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/prelude.rs b/issues/386/src/compact/prelude.rs deleted file mode 100644 index 85cecd87..00000000 --- a/issues/386/src/compact/prelude.rs +++ /dev/null @@ -1,18 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -pub use super::actor::Entity as Actor; -pub use super::address::Entity as Address; -pub use super::category::Entity as Category; -pub use super::city::Entity as City; -pub use super::country::Entity as Country; -pub use super::customer::Entity as Customer; -pub use super::film::Entity as Film; -pub use super::film_actor::Entity as FilmActor; -pub use super::film_category::Entity as FilmCategory; -pub use super::film_text::Entity as FilmText; -pub use super::inventory::Entity as Inventory; -pub use super::language::Entity as Language; -pub use super::payment::Entity as Payment; -pub use super::rental::Entity as Rental; -pub use super::staff::Entity as Staff; -pub use super::store::Entity as Store; diff --git a/issues/386/src/compact/rental.rs b/issues/386/src/compact/rental.rs deleted file mode 100644 index 15c7e9d9..00000000 --- a/issues/386/src/compact/rental.rs +++ /dev/null @@ -1,73 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "rental")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub rental_id: i32, - pub rental_date: DateTime, - pub inventory_id: i32, - pub customer_id: i32, - pub return_date: Option, - #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())")] - pub staff_id: String, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::customer::Entity", - from = "Column::CustomerId", - to = "super::customer::Column::CustomerId", - on_update = "NoAction", - on_delete = "NoAction" - )] - Customer, - #[sea_orm( - belongs_to = "super::inventory::Entity", - from = "Column::InventoryId", - to = "super::inventory::Column::InventoryId", - on_update = "NoAction", - on_delete = "NoAction" - )] - Inventory, - #[sea_orm( - belongs_to = "super::staff::Entity", - from = "Column::StaffId", - to = "super::staff::Column::StaffId", - on_update = "NoAction", - on_delete = "NoAction" - )] - Staff, - #[sea_orm(has_many = "super::payment::Entity")] - Payment, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Customer.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Inventory.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Staff.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Payment.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/staff.rs b/issues/386/src/compact/staff.rs deleted file mode 100644 index 805e5a26..00000000 --- a/issues/386/src/compact/staff.rs +++ /dev/null @@ -1,76 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "staff")] -pub struct Model { - #[sea_orm( - primary_key, - auto_increment = false, - column_type = "Custom(\"BLOB\".to_owned())" - )] - pub staff_id: String, - pub first_name: String, - pub last_name: String, - pub address_id: i32, - #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())", nullable)] - pub picture: Option, - pub email: Option, - pub store_id: i32, - #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())")] - pub active: String, - pub username: String, - pub password: Option, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::address::Entity", - from = "Column::AddressId", - to = "super::address::Column::AddressId", - on_update = "Cascade", - on_delete = "NoAction" - )] - Address, - #[sea_orm( - belongs_to = "super::store::Entity", - from = "Column::StoreId", - to = "super::store::Column::StoreId", - on_update = "Cascade", - on_delete = "NoAction" - )] - Store, - #[sea_orm(has_many = "super::payment::Entity")] - Payment, - #[sea_orm(has_many = "super::rental::Entity")] - Rental, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Address.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Store.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Payment.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Rental.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/compact/store.rs b/issues/386/src/compact/store.rs deleted file mode 100644 index f7e1eb4a..00000000 --- a/issues/386/src/compact/store.rs +++ /dev/null @@ -1,64 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "store")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub store_id: i32, - #[sea_orm(column_type = "Custom(\"BLOB\".to_owned())")] - pub manager_staff_id: String, - pub address_id: i32, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::address::Entity", - from = "Column::AddressId", - to = "super::address::Column::AddressId", - on_update = "NoAction", - on_delete = "NoAction" - )] - Address, - #[sea_orm( - belongs_to = "super::staff::Entity", - from = "Column::ManagerStaffId", - to = "super::staff::Column::StaffId", - on_update = "NoAction", - on_delete = "NoAction" - )] - Staff, - #[sea_orm(has_many = "super::customer::Entity")] - Customer, - #[sea_orm(has_many = "super::inventory::Entity")] - Inventory, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Address.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Staff.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Customer.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Inventory.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/actor.rs b/issues/386/src/expanded/actor.rs deleted file mode 100644 index 578d11b2..00000000 --- a/issues/386/src/expanded/actor.rs +++ /dev/null @@ -1,73 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Copy, Clone, Default, Debug, DeriveEntity)] -pub struct Entity; - -impl EntityName for Entity { - fn table_name(&self) -> &str { - "actor" - } -} - -#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] -pub struct Model { - pub actor_id: i32, - pub first_name: String, - pub last_name: String, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] -pub enum Column { - ActorId, - FirstName, - LastName, - LastUpdate, -} - -#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] -pub enum PrimaryKey { - ActorId, -} - -impl PrimaryKeyTrait for PrimaryKey { - type ValueType = i32; - fn auto_increment() -> bool { - true - } -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation { - FilmActor, -} - -impl ColumnTrait for Column { - type EntityName = Entity; - fn def(&self) -> ColumnDef { - match self { - Self::ActorId => ColumnType::Integer.def(), - Self::FirstName => ColumnType::String(None).def(), - Self::LastName => ColumnType::String(None).def(), - Self::LastUpdate => ColumnType::Timestamp.def(), - } - } -} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - match self { - Self::FilmActor => Entity::has_many(super::film_actor::Entity).into(), - } - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::FilmActor.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/address.rs b/issues/386/src/expanded/address.rs deleted file mode 100644 index e8b9a5b8..00000000 --- a/issues/386/src/expanded/address.rs +++ /dev/null @@ -1,112 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Copy, Clone, Default, Debug, DeriveEntity)] -pub struct Entity; - -impl EntityName for Entity { - fn table_name(&self) -> &str { - "address" - } -} - -#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] -pub struct Model { - pub address_id: i32, - pub address: String, - pub address2: Option, - pub district: String, - pub city_id: i32, - pub postal_code: Option, - pub phone: String, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] -pub enum Column { - AddressId, - Address, - Address2, - District, - CityId, - PostalCode, - Phone, - LastUpdate, -} - -#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] -pub enum PrimaryKey { - AddressId, -} - -impl PrimaryKeyTrait for PrimaryKey { - type ValueType = i32; - fn auto_increment() -> bool { - false - } -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation { - City, - Customer, - Staff, - Store, -} - -impl ColumnTrait for Column { - type EntityName = Entity; - fn def(&self) -> ColumnDef { - match self { - Self::AddressId => ColumnType::Integer.def(), - Self::Address => ColumnType::String(None).def(), - Self::Address2 => ColumnType::String(None).def().null(), - Self::District => ColumnType::String(None).def(), - Self::CityId => ColumnType::Integer.def(), - Self::PostalCode => ColumnType::String(None).def().null(), - Self::Phone => ColumnType::String(None).def(), - Self::LastUpdate => ColumnType::Timestamp.def(), - } - } -} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - match self { - Self::City => Entity::belongs_to(super::city::Entity) - .from(Column::CityId) - .to(super::city::Column::CityId) - .into(), - Self::Customer => Entity::has_many(super::customer::Entity).into(), - Self::Staff => Entity::has_many(super::staff::Entity).into(), - Self::Store => Entity::has_many(super::store::Entity).into(), - } - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::City.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Customer.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Staff.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Store.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/category.rs b/issues/386/src/expanded/category.rs deleted file mode 100644 index 4ce53b6a..00000000 --- a/issues/386/src/expanded/category.rs +++ /dev/null @@ -1,70 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Copy, Clone, Default, Debug, DeriveEntity)] -pub struct Entity; - -impl EntityName for Entity { - fn table_name(&self) -> &str { - "category" - } -} - -#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] -pub struct Model { - pub category_id: String, - pub name: String, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] -pub enum Column { - CategoryId, - Name, - LastUpdate, -} - -#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] -pub enum PrimaryKey { - CategoryId, -} - -impl PrimaryKeyTrait for PrimaryKey { - type ValueType = String; - fn auto_increment() -> bool { - false - } -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation { - FilmCategory, -} - -impl ColumnTrait for Column { - type EntityName = Entity; - fn def(&self) -> ColumnDef { - match self { - Self::CategoryId => ColumnType::Custom("BLOB".to_owned()).def(), - Self::Name => ColumnType::String(None).def(), - Self::LastUpdate => ColumnType::Timestamp.def(), - } - } -} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - match self { - Self::FilmCategory => Entity::has_many(super::film_category::Entity).into(), - } - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::FilmCategory.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/city.rs b/issues/386/src/expanded/city.rs deleted file mode 100644 index eb4010d2..00000000 --- a/issues/386/src/expanded/city.rs +++ /dev/null @@ -1,84 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Copy, Clone, Default, Debug, DeriveEntity)] -pub struct Entity; - -impl EntityName for Entity { - fn table_name(&self) -> &str { - "city" - } -} - -#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] -pub struct Model { - pub city_id: i32, - pub city: String, - pub country_id: String, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] -pub enum Column { - CityId, - City, - CountryId, - LastUpdate, -} - -#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] -pub enum PrimaryKey { - CityId, -} - -impl PrimaryKeyTrait for PrimaryKey { - type ValueType = i32; - fn auto_increment() -> bool { - false - } -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation { - Country, - Address, -} - -impl ColumnTrait for Column { - type EntityName = Entity; - fn def(&self) -> ColumnDef { - match self { - Self::CityId => ColumnType::Integer.def(), - Self::City => ColumnType::String(None).def(), - Self::CountryId => ColumnType::Custom("BLOB".to_owned()).def(), - Self::LastUpdate => ColumnType::Timestamp.def(), - } - } -} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - match self { - Self::Country => Entity::belongs_to(super::country::Entity) - .from(Column::CountryId) - .to(super::country::Column::CountryId) - .into(), - Self::Address => Entity::has_many(super::address::Entity).into(), - } - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Country.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Address.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/country.rs b/issues/386/src/expanded/country.rs deleted file mode 100644 index 5901ccbc..00000000 --- a/issues/386/src/expanded/country.rs +++ /dev/null @@ -1,70 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Copy, Clone, Default, Debug, DeriveEntity)] -pub struct Entity; - -impl EntityName for Entity { - fn table_name(&self) -> &str { - "country" - } -} - -#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] -pub struct Model { - pub country_id: String, - pub country: String, - pub last_update: Option, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] -pub enum Column { - CountryId, - Country, - LastUpdate, -} - -#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] -pub enum PrimaryKey { - CountryId, -} - -impl PrimaryKeyTrait for PrimaryKey { - type ValueType = String; - fn auto_increment() -> bool { - false - } -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation { - City, -} - -impl ColumnTrait for Column { - type EntityName = Entity; - fn def(&self) -> ColumnDef { - match self { - Self::CountryId => ColumnType::Custom("BLOB".to_owned()).def(), - Self::Country => ColumnType::String(None).def(), - Self::LastUpdate => ColumnType::Timestamp.def().null(), - } - } -} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - match self { - Self::City => Entity::has_many(super::city::Entity).into(), - } - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::City.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/customer.rs b/issues/386/src/expanded/customer.rs deleted file mode 100644 index 1adbaa66..00000000 --- a/issues/386/src/expanded/customer.rs +++ /dev/null @@ -1,118 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Copy, Clone, Default, Debug, DeriveEntity)] -pub struct Entity; - -impl EntityName for Entity { - fn table_name(&self) -> &str { - "customer" - } -} - -#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] -pub struct Model { - pub customer_id: i32, - pub store_id: i32, - pub first_name: String, - pub last_name: String, - pub email: Option, - pub address_id: i32, - pub active: String, - pub create_date: DateTime, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] -pub enum Column { - CustomerId, - StoreId, - FirstName, - LastName, - Email, - AddressId, - Active, - CreateDate, - LastUpdate, -} - -#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] -pub enum PrimaryKey { - CustomerId, -} - -impl PrimaryKeyTrait for PrimaryKey { - type ValueType = i32; - fn auto_increment() -> bool { - false - } -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation { - Address, - Store, - Payment, - Rental, -} - -impl ColumnTrait for Column { - type EntityName = Entity; - fn def(&self) -> ColumnDef { - match self { - Self::CustomerId => ColumnType::Integer.def(), - Self::StoreId => ColumnType::Integer.def(), - Self::FirstName => ColumnType::String(None).def(), - Self::LastName => ColumnType::String(None).def(), - Self::Email => ColumnType::String(None).def().null(), - Self::AddressId => ColumnType::Integer.def(), - Self::Active => ColumnType::Custom("BLOB".to_owned()).def(), - Self::CreateDate => ColumnType::Timestamp.def(), - Self::LastUpdate => ColumnType::Timestamp.def(), - } - } -} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - match self { - Self::Address => Entity::belongs_to(super::address::Entity) - .from(Column::AddressId) - .to(super::address::Column::AddressId) - .into(), - Self::Store => Entity::belongs_to(super::store::Entity) - .from(Column::StoreId) - .to(super::store::Column::StoreId) - .into(), - Self::Payment => Entity::has_many(super::payment::Entity).into(), - Self::Rental => Entity::has_many(super::rental::Entity).into(), - } - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Address.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Store.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Payment.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Rental.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/film.rs b/issues/386/src/expanded/film.rs deleted file mode 100644 index b4e12ce3..00000000 --- a/issues/386/src/expanded/film.rs +++ /dev/null @@ -1,126 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Copy, Clone, Default, Debug, DeriveEntity)] -pub struct Entity; - -impl EntityName for Entity { - fn table_name(&self) -> &str { - "film" - } -} - -#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] -pub struct Model { - pub film_id: i32, - pub title: String, - pub description: Option, - pub release_year: Option, - pub language_id: String, - pub original_language_id: Option, - pub rental_duration: String, - pub rental_rate: Decimal, - pub length: Option, - pub replacement_cost: Decimal, - pub rating: Option, - pub special_features: Option, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] -pub enum Column { - FilmId, - Title, - Description, - ReleaseYear, - LanguageId, - OriginalLanguageId, - RentalDuration, - RentalRate, - Length, - ReplacementCost, - Rating, - SpecialFeatures, - LastUpdate, -} - -#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] -pub enum PrimaryKey { - FilmId, -} - -impl PrimaryKeyTrait for PrimaryKey { - type ValueType = i32; - fn auto_increment() -> bool { - false - } -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation { - Language2, - Language1, - FilmActor, - FilmCategory, - Inventory, -} - -impl ColumnTrait for Column { - type EntityName = Entity; - fn def(&self) -> ColumnDef { - match self { - Self::FilmId => ColumnType::Integer.def(), - Self::Title => ColumnType::String(None).def(), - Self::Description => ColumnType::Custom("BLOB".to_owned()).def().null(), - Self::ReleaseYear => ColumnType::String(None).def().null(), - Self::LanguageId => ColumnType::Custom("BLOB".to_owned()).def(), - Self::OriginalLanguageId => ColumnType::Custom("BLOB".to_owned()).def().null(), - Self::RentalDuration => ColumnType::Custom("BLOB".to_owned()).def(), - Self::RentalRate => ColumnType::Decimal(Some((4u32, 2u32))).def(), - Self::Length => ColumnType::Custom("BLOB".to_owned()).def().null(), - Self::ReplacementCost => ColumnType::Decimal(Some((5u32, 2u32))).def(), - Self::Rating => ColumnType::String(None).def().null(), - Self::SpecialFeatures => ColumnType::String(None).def().null(), - Self::LastUpdate => ColumnType::Timestamp.def(), - } - } -} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - match self { - Self::Language2 => Entity::belongs_to(super::language::Entity) - .from(Column::OriginalLanguageId) - .to(super::language::Column::LanguageId) - .into(), - Self::Language1 => Entity::belongs_to(super::language::Entity) - .from(Column::LanguageId) - .to(super::language::Column::LanguageId) - .into(), - Self::FilmActor => Entity::has_many(super::film_actor::Entity).into(), - Self::FilmCategory => Entity::has_many(super::film_category::Entity).into(), - Self::Inventory => Entity::has_many(super::inventory::Entity).into(), - } - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::FilmActor.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::FilmCategory.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Inventory.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/film_actor.rs b/issues/386/src/expanded/film_actor.rs deleted file mode 100644 index 86211cec..00000000 --- a/issues/386/src/expanded/film_actor.rs +++ /dev/null @@ -1,85 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Copy, Clone, Default, Debug, DeriveEntity)] -pub struct Entity; - -impl EntityName for Entity { - fn table_name(&self) -> &str { - "film_actor" - } -} - -#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] -pub struct Model { - pub actor_id: i32, - pub film_id: i32, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] -pub enum Column { - ActorId, - FilmId, - LastUpdate, -} - -#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] -pub enum PrimaryKey { - ActorId, - FilmId, -} - -impl PrimaryKeyTrait for PrimaryKey { - type ValueType = (i32, i32); - fn auto_increment() -> bool { - false - } -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation { - Film, - Actor, -} - -impl ColumnTrait for Column { - type EntityName = Entity; - fn def(&self) -> ColumnDef { - match self { - Self::ActorId => ColumnType::Integer.def(), - Self::FilmId => ColumnType::Integer.def(), - Self::LastUpdate => ColumnType::Timestamp.def(), - } - } -} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - match self { - Self::Film => Entity::belongs_to(super::film::Entity) - .from(Column::FilmId) - .to(super::film::Column::FilmId) - .into(), - Self::Actor => Entity::belongs_to(super::actor::Entity) - .from(Column::ActorId) - .to(super::actor::Column::ActorId) - .into(), - } - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Film.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Actor.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/film_category.rs b/issues/386/src/expanded/film_category.rs deleted file mode 100644 index c1cc118a..00000000 --- a/issues/386/src/expanded/film_category.rs +++ /dev/null @@ -1,85 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Copy, Clone, Default, Debug, DeriveEntity)] -pub struct Entity; - -impl EntityName for Entity { - fn table_name(&self) -> &str { - "film_category" - } -} - -#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] -pub struct Model { - pub film_id: i32, - pub category_id: String, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] -pub enum Column { - FilmId, - CategoryId, - LastUpdate, -} - -#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] -pub enum PrimaryKey { - FilmId, - CategoryId, -} - -impl PrimaryKeyTrait for PrimaryKey { - type ValueType = (i32, String); - fn auto_increment() -> bool { - false - } -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation { - Category, - Film, -} - -impl ColumnTrait for Column { - type EntityName = Entity; - fn def(&self) -> ColumnDef { - match self { - Self::FilmId => ColumnType::Integer.def(), - Self::CategoryId => ColumnType::Custom("BLOB".to_owned()).def(), - Self::LastUpdate => ColumnType::Timestamp.def(), - } - } -} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - match self { - Self::Category => Entity::belongs_to(super::category::Entity) - .from(Column::CategoryId) - .to(super::category::Column::CategoryId) - .into(), - Self::Film => Entity::belongs_to(super::film::Entity) - .from(Column::FilmId) - .to(super::film::Column::FilmId) - .into(), - } - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Category.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Film.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/film_text.rs b/issues/386/src/expanded/film_text.rs deleted file mode 100644 index 87dbeda4..00000000 --- a/issues/386/src/expanded/film_text.rs +++ /dev/null @@ -1,60 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Copy, Clone, Default, Debug, DeriveEntity)] -pub struct Entity; - -impl EntityName for Entity { - fn table_name(&self) -> &str { - "film_text" - } -} - -#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] -pub struct Model { - pub film_id: String, - pub title: String, - pub description: Option, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] -pub enum Column { - FilmId, - Title, - Description, -} - -#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] -pub enum PrimaryKey { - FilmId, -} - -impl PrimaryKeyTrait for PrimaryKey { - type ValueType = String; - fn auto_increment() -> bool { - false - } -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation {} - -impl ColumnTrait for Column { - type EntityName = Entity; - fn def(&self) -> ColumnDef { - match self { - Self::FilmId => ColumnType::Custom("BLOB".to_owned()).def(), - Self::Title => ColumnType::String(None).def(), - Self::Description => ColumnType::Custom("BLOB".to_owned()).def().null(), - } - } -} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - panic!("No RelationDef") - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/inventory.rs b/issues/386/src/expanded/inventory.rs deleted file mode 100644 index dbbb412b..00000000 --- a/issues/386/src/expanded/inventory.rs +++ /dev/null @@ -1,95 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Copy, Clone, Default, Debug, DeriveEntity)] -pub struct Entity; - -impl EntityName for Entity { - fn table_name(&self) -> &str { - "inventory" - } -} - -#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] -pub struct Model { - pub inventory_id: i32, - pub film_id: i32, - pub store_id: i32, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] -pub enum Column { - InventoryId, - FilmId, - StoreId, - LastUpdate, -} - -#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] -pub enum PrimaryKey { - InventoryId, -} - -impl PrimaryKeyTrait for PrimaryKey { - type ValueType = i32; - fn auto_increment() -> bool { - false - } -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation { - Film, - Store, - Rental, -} - -impl ColumnTrait for Column { - type EntityName = Entity; - fn def(&self) -> ColumnDef { - match self { - Self::InventoryId => ColumnType::Integer.def(), - Self::FilmId => ColumnType::Integer.def(), - Self::StoreId => ColumnType::Integer.def(), - Self::LastUpdate => ColumnType::Timestamp.def(), - } - } -} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - match self { - Self::Film => Entity::belongs_to(super::film::Entity) - .from(Column::FilmId) - .to(super::film::Column::FilmId) - .into(), - Self::Store => Entity::belongs_to(super::store::Entity) - .from(Column::StoreId) - .to(super::store::Column::StoreId) - .into(), - Self::Rental => Entity::has_many(super::rental::Entity).into(), - } - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Film.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Store.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Rental.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/language.rs b/issues/386/src/expanded/language.rs deleted file mode 100644 index cffd118e..00000000 --- a/issues/386/src/expanded/language.rs +++ /dev/null @@ -1,60 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Copy, Clone, Default, Debug, DeriveEntity)] -pub struct Entity; - -impl EntityName for Entity { - fn table_name(&self) -> &str { - "language" - } -} - -#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] -pub struct Model { - pub language_id: String, - pub name: String, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] -pub enum Column { - LanguageId, - Name, - LastUpdate, -} - -#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] -pub enum PrimaryKey { - LanguageId, -} - -impl PrimaryKeyTrait for PrimaryKey { - type ValueType = String; - fn auto_increment() -> bool { - false - } -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation {} - -impl ColumnTrait for Column { - type EntityName = Entity; - fn def(&self) -> ColumnDef { - match self { - Self::LanguageId => ColumnType::Custom("BLOB".to_owned()).def(), - Self::Name => ColumnType::Custom("BLOB".to_owned()).def(), - Self::LastUpdate => ColumnType::Timestamp.def(), - } - } -} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - panic!("No RelationDef") - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/mod.rs b/issues/386/src/expanded/mod.rs deleted file mode 100644 index d7f098fc..00000000 --- a/issues/386/src/expanded/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -pub mod prelude; - -pub mod actor; -pub mod address; -pub mod category; -pub mod city; -pub mod country; -pub mod customer; -pub mod film; -pub mod film_actor; -pub mod film_category; -pub mod film_text; -pub mod inventory; -pub mod language; -pub mod payment; -pub mod rental; -pub mod staff; -pub mod store; diff --git a/issues/386/src/expanded/payment.rs b/issues/386/src/expanded/payment.rs deleted file mode 100644 index 7977464b..00000000 --- a/issues/386/src/expanded/payment.rs +++ /dev/null @@ -1,107 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Copy, Clone, Default, Debug, DeriveEntity)] -pub struct Entity; - -impl EntityName for Entity { - fn table_name(&self) -> &str { - "payment" - } -} - -#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] -pub struct Model { - pub payment_id: i32, - pub customer_id: i32, - pub staff_id: String, - pub rental_id: Option, - pub amount: Decimal, - pub payment_date: DateTime, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] -pub enum Column { - PaymentId, - CustomerId, - StaffId, - RentalId, - Amount, - PaymentDate, - LastUpdate, -} - -#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] -pub enum PrimaryKey { - PaymentId, -} - -impl PrimaryKeyTrait for PrimaryKey { - type ValueType = i32; - fn auto_increment() -> bool { - false - } -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation { - Staff, - Customer, - Rental, -} - -impl ColumnTrait for Column { - type EntityName = Entity; - fn def(&self) -> ColumnDef { - match self { - Self::PaymentId => ColumnType::Integer.def(), - Self::CustomerId => ColumnType::Integer.def(), - Self::StaffId => ColumnType::Custom("BLOB".to_owned()).def(), - Self::RentalId => ColumnType::Integer.def().null(), - Self::Amount => ColumnType::Decimal(Some((5u32, 2u32))).def(), - Self::PaymentDate => ColumnType::Timestamp.def(), - Self::LastUpdate => ColumnType::Timestamp.def(), - } - } -} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - match self { - Self::Staff => Entity::belongs_to(super::staff::Entity) - .from(Column::StaffId) - .to(super::staff::Column::StaffId) - .into(), - Self::Customer => Entity::belongs_to(super::customer::Entity) - .from(Column::CustomerId) - .to(super::customer::Column::CustomerId) - .into(), - Self::Rental => Entity::belongs_to(super::rental::Entity) - .from(Column::RentalId) - .to(super::rental::Column::RentalId) - .into(), - } - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Staff.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Customer.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Rental.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/prelude.rs b/issues/386/src/expanded/prelude.rs deleted file mode 100644 index 85cecd87..00000000 --- a/issues/386/src/expanded/prelude.rs +++ /dev/null @@ -1,18 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -pub use super::actor::Entity as Actor; -pub use super::address::Entity as Address; -pub use super::category::Entity as Category; -pub use super::city::Entity as City; -pub use super::country::Entity as Country; -pub use super::customer::Entity as Customer; -pub use super::film::Entity as Film; -pub use super::film_actor::Entity as FilmActor; -pub use super::film_category::Entity as FilmCategory; -pub use super::film_text::Entity as FilmText; -pub use super::inventory::Entity as Inventory; -pub use super::language::Entity as Language; -pub use super::payment::Entity as Payment; -pub use super::rental::Entity as Rental; -pub use super::staff::Entity as Staff; -pub use super::store::Entity as Store; diff --git a/issues/386/src/expanded/rental.rs b/issues/386/src/expanded/rental.rs deleted file mode 100644 index 952a0285..00000000 --- a/issues/386/src/expanded/rental.rs +++ /dev/null @@ -1,115 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Copy, Clone, Default, Debug, DeriveEntity)] -pub struct Entity; - -impl EntityName for Entity { - fn table_name(&self) -> &str { - "rental" - } -} - -#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] -pub struct Model { - pub rental_id: i32, - pub rental_date: DateTime, - pub inventory_id: i32, - pub customer_id: i32, - pub return_date: Option, - pub staff_id: String, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] -pub enum Column { - RentalId, - RentalDate, - InventoryId, - CustomerId, - ReturnDate, - StaffId, - LastUpdate, -} - -#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] -pub enum PrimaryKey { - RentalId, -} - -impl PrimaryKeyTrait for PrimaryKey { - type ValueType = i32; - fn auto_increment() -> bool { - false - } -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation { - Customer, - Inventory, - Staff, - Payment, -} - -impl ColumnTrait for Column { - type EntityName = Entity; - fn def(&self) -> ColumnDef { - match self { - Self::RentalId => ColumnType::Integer.def(), - Self::RentalDate => ColumnType::Timestamp.def(), - Self::InventoryId => ColumnType::Integer.def(), - Self::CustomerId => ColumnType::Integer.def(), - Self::ReturnDate => ColumnType::Timestamp.def().null(), - Self::StaffId => ColumnType::Custom("BLOB".to_owned()).def(), - Self::LastUpdate => ColumnType::Timestamp.def(), - } - } -} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - match self { - Self::Customer => Entity::belongs_to(super::customer::Entity) - .from(Column::CustomerId) - .to(super::customer::Column::CustomerId) - .into(), - Self::Inventory => Entity::belongs_to(super::inventory::Entity) - .from(Column::InventoryId) - .to(super::inventory::Column::InventoryId) - .into(), - Self::Staff => Entity::belongs_to(super::staff::Entity) - .from(Column::StaffId) - .to(super::staff::Column::StaffId) - .into(), - Self::Payment => Entity::has_many(super::payment::Entity).into(), - } - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Customer.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Inventory.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Staff.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Payment.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/staff.rs b/issues/386/src/expanded/staff.rs deleted file mode 100644 index a24721cf..00000000 --- a/issues/386/src/expanded/staff.rs +++ /dev/null @@ -1,124 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Copy, Clone, Default, Debug, DeriveEntity)] -pub struct Entity; - -impl EntityName for Entity { - fn table_name(&self) -> &str { - "staff" - } -} - -#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] -pub struct Model { - pub staff_id: String, - pub first_name: String, - pub last_name: String, - pub address_id: i32, - pub picture: Option, - pub email: Option, - pub store_id: i32, - pub active: String, - pub username: String, - pub password: Option, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] -pub enum Column { - StaffId, - FirstName, - LastName, - AddressId, - Picture, - Email, - StoreId, - Active, - Username, - Password, - LastUpdate, -} - -#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] -pub enum PrimaryKey { - StaffId, -} - -impl PrimaryKeyTrait for PrimaryKey { - type ValueType = String; - fn auto_increment() -> bool { - false - } -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation { - Address, - Store, - Payment, - Rental, -} - -impl ColumnTrait for Column { - type EntityName = Entity; - fn def(&self) -> ColumnDef { - match self { - Self::StaffId => ColumnType::Custom("BLOB".to_owned()).def(), - Self::FirstName => ColumnType::String(None).def(), - Self::LastName => ColumnType::String(None).def(), - Self::AddressId => ColumnType::Integer.def(), - Self::Picture => ColumnType::Custom("BLOB".to_owned()).def().null(), - Self::Email => ColumnType::String(None).def().null(), - Self::StoreId => ColumnType::Integer.def(), - Self::Active => ColumnType::Custom("BLOB".to_owned()).def(), - Self::Username => ColumnType::String(None).def(), - Self::Password => ColumnType::String(None).def().null(), - Self::LastUpdate => ColumnType::Timestamp.def(), - } - } -} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - match self { - Self::Address => Entity::belongs_to(super::address::Entity) - .from(Column::AddressId) - .to(super::address::Column::AddressId) - .into(), - Self::Store => Entity::belongs_to(super::store::Entity) - .from(Column::StoreId) - .to(super::store::Column::StoreId) - .into(), - Self::Payment => Entity::has_many(super::payment::Entity).into(), - Self::Rental => Entity::has_many(super::rental::Entity).into(), - } - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Address.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Store.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Payment.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Rental.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/expanded/store.rs b/issues/386/src/expanded/store.rs deleted file mode 100644 index 1d04fd66..00000000 --- a/issues/386/src/expanded/store.rs +++ /dev/null @@ -1,103 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.4.2 - -use sea_orm::entity::prelude::*; - -#[derive(Copy, Clone, Default, Debug, DeriveEntity)] -pub struct Entity; - -impl EntityName for Entity { - fn table_name(&self) -> &str { - "store" - } -} - -#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] -pub struct Model { - pub store_id: i32, - pub manager_staff_id: String, - pub address_id: i32, - pub last_update: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] -pub enum Column { - StoreId, - ManagerStaffId, - AddressId, - LastUpdate, -} - -#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] -pub enum PrimaryKey { - StoreId, -} - -impl PrimaryKeyTrait for PrimaryKey { - type ValueType = i32; - fn auto_increment() -> bool { - false - } -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation { - Address, - Staff, - Customer, - Inventory, -} - -impl ColumnTrait for Column { - type EntityName = Entity; - fn def(&self) -> ColumnDef { - match self { - Self::StoreId => ColumnType::Integer.def(), - Self::ManagerStaffId => ColumnType::Custom("BLOB".to_owned()).def(), - Self::AddressId => ColumnType::Integer.def(), - Self::LastUpdate => ColumnType::Timestamp.def(), - } - } -} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - match self { - Self::Address => Entity::belongs_to(super::address::Entity) - .from(Column::AddressId) - .to(super::address::Column::AddressId) - .into(), - Self::Staff => Entity::belongs_to(super::staff::Entity) - .from(Column::ManagerStaffId) - .to(super::staff::Column::StaffId) - .into(), - Self::Customer => Entity::has_many(super::customer::Entity).into(), - Self::Inventory => Entity::has_many(super::inventory::Entity).into(), - } - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Address.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Staff.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Customer.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Inventory.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/issues/386/src/main.rs b/issues/386/src/main.rs deleted file mode 100644 index c76f4650..00000000 --- a/issues/386/src/main.rs +++ /dev/null @@ -1,4 +0,0 @@ -mod compact; -mod expanded; - -pub fn main() {} From 49808108676c646fcc141f9be02c06fd71bdcf1f Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Sat, 25 Dec 2021 13:34:49 +0800 Subject: [PATCH 36/36] ci: run simple clippy --- .github/workflows/rust.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 4affff66..17819f23 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -108,10 +108,12 @@ jobs: --all # Run clippy - - uses: actions-rs/clippy-check@v1 + - uses: actions-rs/cargo@v1 with: - token: ${{ secrets.GITHUB_TOKEN }} - args: --all-targets --all + command: clippy + args: > + --all-targets + --all compile-sqlite: name: Compile SQLite