From 2563e048db3209a8c09501d3afef7e320d9e26e4 Mon Sep 17 00:00:00 2001 From: Yiu Tin Cheung Ivan Date: Thu, 6 Jul 2023 18:51:18 +0800 Subject: [PATCH 01/11] WIP, implementing Iden --- sea-orm-macros/src/derives/iden.rs | 150 +++++++++++++++++++++++++++++ sea-orm-macros/src/derives/mod.rs | 2 + sea-orm-macros/src/lib.rs | 23 +++++ src/lib.rs | 4 +- 4 files changed, 177 insertions(+), 2 deletions(-) create mode 100644 sea-orm-macros/src/derives/iden.rs diff --git a/sea-orm-macros/src/derives/iden.rs b/sea-orm-macros/src/derives/iden.rs new file mode 100644 index 000000000..ca8b390b4 --- /dev/null +++ b/sea-orm-macros/src/derives/iden.rs @@ -0,0 +1,150 @@ +use std::convert::{TryFrom, TryInto}; + +use heck::ToSnakeCase; +use proc_macro2::{self, TokenStream, Ident}; +use quote::{quote, quote_spanned}; +use syn::{parse_macro_input, Attribute, DataEnum, DataStruct, DeriveInput, Fields, Variant, Error, Expr, LitStr}; + + +fn must_be_valid_iden(name: &str) -> bool { + // can only begin with [a-z_] + name.chars() + .take(1) + .all(|c| c == '_' || c.is_ascii_alphabetic()) + && name.chars().all(|c| c == '_' || c.is_ascii_alphanumeric()) +} + +fn impl_iden_for_unit_struct( + ident: &proc_macro2::Ident, + table_name: &str, +) -> proc_macro2::TokenStream { + let prepare = if must_be_valid_iden(table_name) { + quote! { + fn prepare(&self, s: &mut dyn ::std::fmt::Write, q: sea_query::Quote) { + write!(s, "{}", q.left()).unwrap(); + self.unquoted(s); + write!(s, "{}", q.right()).unwrap(); + } + } + } else { + quote! {} + }; + quote! { + impl sea_query::Iden for #ident { + #prepare + + fn unquoted(&self, s: &mut dyn ::std::fmt::Write) { + write!(s, #table_name).unwrap(); + } + } + } +} + +fn try_from((table_name, value): (&'a str, &'a Variant)) -> Result { + let Variant { + ident, + fields, + attrs, + .. + } = value; + let attr = find_attr(attrs).map(IdenAttr::try_from).transpose()?; + + Self::new(ident, fields, table_name, attr) +} + +fn impl_iden_for_enum<'a, T>( + ident: &proc_macro2::Ident, + table_name: &str, + variants: T, +) -> proc_macro2::TokenStream +where + T: Iterator, +{ + let mut is_all_valid = true; + + let match_arms = match variants + .map(|v| (table_name, v)) + .map(|v| { + let v = try_from(v)?; + is_all_valid &= v.must_be_valid_iden(); + Ok(v) + }) + .collect::>>() + { + Ok(v) => quote! { #(#v),* }, + Err(e) => return e.to_compile_error(), + }; + + let prepare = if is_all_valid { + quote! { + fn prepare(&self, s: &mut dyn ::std::fmt::Write, q: sea_query::Quote) { + write!(s, "{}", q.left()).unwrap(); + self.unquoted(s); + write!(s, "{}", q.right()).unwrap(); + } + } + } else { + quote! {} + }; + + quote! { + impl sea_query::Iden for #ident { + #prepare + + fn unquoted(&self, s: &mut dyn ::std::fmt::Write) { + match self { + #match_arms + }; + } + } + } +} + +pub fn expand_derive_iden(input: DeriveInput) -> syn::Result { + let DeriveInput { + ident, data, attrs, .. + } = input; + + let table_name = ident.to_string(); + + let mut new_name: TokenStream = quote!(); + input + .attrs + .iter() + .filter(|attr| attr.path().is_ident("sea_orm")) + .try_for_each(|attr| { + attr.parse_nested_meta(|meta| { + if meta.path.is_ident("iden") { + let litstr: LitStr = meta.value()?.parse()?; + new_name = syn::parse_str::(&litstr.value()).expect("iden attribute should contain something"); + } else { + // Reads the value expression to advance the parse stream. + // Some parameters do not have any value, + // so ignoring an error occurred here. + let _: Option = meta.value().and_then(|v| v.parse()).ok(); + } + Ok(()) + }) + })?; + + // Currently we only support enums and unit structs + let variants = + match data { + syn::Data::Enum(DataEnum { variants, .. }) => variants, + syn::Data::Struct(DataStruct { + fields: Fields::Unit, + .. + }) => return impl_iden_for_unit_struct(&ident, &table_name).into(), + _ => return Ok(quote_spanned! { + ident.span() => compile_error!("you can only derive DeriveIden on unit struct or enum"); + }) + }; + + if variants.is_empty() { + return variants; //todo : find good error + } + + let output = impl_iden_for_enum(&ident, &table_name, variants.iter()); + + Ok(output) +} \ No newline at end of file diff --git a/sea-orm-macros/src/derives/mod.rs b/sea-orm-macros/src/derives/mod.rs index 29f69b053..982dc064f 100644 --- a/sea-orm-macros/src/derives/mod.rs +++ b/sea-orm-macros/src/derives/mod.rs @@ -15,6 +15,7 @@ mod related_entity; mod relation; mod try_getable_from_json; mod util; +mod iden; pub use active_enum::*; pub use active_model::*; @@ -31,3 +32,4 @@ pub use primary_key::*; pub use related_entity::*; pub use relation::*; pub use try_getable_from_json::*; +pub use iden::*; \ No newline at end of file diff --git a/sea-orm-macros/src/lib.rs b/sea-orm-macros/src/lib.rs index 0e9c7b1b8..32ac72f7a 100644 --- a/sea-orm-macros/src/lib.rs +++ b/sea-orm-macros/src/lib.rs @@ -832,3 +832,26 @@ pub fn enum_iter(input: TokenStream) -> TokenStream { .unwrap_or_else(Error::into_compile_error) .into() } + + +// #[proc_macro_derive(Iden, attributes(iden, method))] +// pub fn iden(input: TokenStream) -> TokenStream { +// let input = parse_macro_input!(input as DeriveInput); +// if cfg!(feature = "sea-query"){ +// crate::derive_iden(input) +// } +// else { +// sea_orm::derive_iden(input) +// } +// } + +#[cfg(feature = "derive")] +#[proc_macro_derive(DeriveIden, attributes(sea_orm))] +pub fn derive_iden(input: TokenStream) -> TokenStream { + let derive_input = parse_macro_input!(input as DeriveInput); + + match derives::expand_derive_iden(derive_input) { + Ok(token_stream) => token_stream.into(), + Err(e) => e.to_compile_error().into(), + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 15e13e595..f4034da72 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -356,8 +356,8 @@ pub use sea_orm_macros::{ pub use sea_query; pub use sea_query::Iden; -#[cfg(feature = "macros")] -pub use sea_query::Iden as DeriveIden; +// #[cfg(feature = "macros")] +// pub use sea_query::Iden as DeriveIden; pub use sea_orm_macros::EnumIter; pub use strum; From 00cd22dbdbb995c6aee4e492e20c025fc7666fd6 Mon Sep 17 00:00:00 2001 From: Yiu Tin Cheung Ivan Date: Mon, 10 Jul 2023 17:46:11 +0800 Subject: [PATCH 02/11] completed implementation for DeriveIden and added basic test cases --- sea-orm-macros/src/derives/derive_iden.rs | 147 +++++++++++++++++++++ sea-orm-macros/src/derives/iden.rs | 150 ---------------------- sea-orm-macros/src/derives/mod.rs | 4 +- sea-orm-macros/src/lib.rs | 54 ++++++-- src/lib.rs | 4 +- tests/derive_iden.rs | 37 ++++++ 6 files changed, 228 insertions(+), 168 deletions(-) create mode 100644 sea-orm-macros/src/derives/derive_iden.rs delete mode 100644 sea-orm-macros/src/derives/iden.rs create mode 100644 tests/derive_iden.rs diff --git a/sea-orm-macros/src/derives/derive_iden.rs b/sea-orm-macros/src/derives/derive_iden.rs new file mode 100644 index 000000000..19307e371 --- /dev/null +++ b/sea-orm-macros/src/derives/derive_iden.rs @@ -0,0 +1,147 @@ +use heck::ToSnakeCase; +use proc_macro2::{self, TokenStream}; +use quote::{quote, quote_spanned}; +use syn::{ + punctuated::Punctuated, DataEnum, DataStruct, DeriveInput, Expr, Fields, LitStr, Variant, +}; + +fn must_be_valid_iden(name: &str) -> bool { + // can only begin with [a-z_] + name.chars() + .take(1) + .all(|c| c == '_' || c.is_ascii_alphabetic()) + && name.chars().all(|c| c == '_' || c.is_ascii_alphanumeric()) +} + +fn impl_iden_for_unit_struct( + ident: &proc_macro2::Ident, + new_iden: &str, +) -> proc_macro2::TokenStream { + let prepare = if must_be_valid_iden(new_iden) { + quote! { + fn prepare(&self, s: &mut dyn ::std::fmt::Write, q: sea_orm::sea_query::Quote) { + write!(s, "{}", q.left()).unwrap(); + self.unquoted(s); + write!(s, "{}", q.right()).unwrap(); + } + } + } else { + quote! {} + }; + quote! { + impl sea_orm::sea_query::Iden for #ident { + #prepare + + fn unquoted(&self, s: &mut dyn ::std::fmt::Write) { + write!(s, #new_iden).unwrap(); + } + } + } +} + +fn impl_iden_for_enum( + ident: &proc_macro2::Ident, + variants: Punctuated, +) -> proc_macro2::TokenStream { + let variants = variants.iter(); + let mut all_valid = true; + + let match_pair: Vec = variants + .map(|v| { + let var_ident = &v.ident; + let mut var_name = var_ident.to_string().to_snake_case(); + v.attrs + .iter() + .filter(|attr| attr.path().is_ident("sea_orm")) + .try_for_each(|attr| { + attr.parse_nested_meta(|meta| { + if meta.path.is_ident("iden") { + let litstr: LitStr = meta.value()?.parse()?; + var_name = litstr.value().to_snake_case(); + all_valid &= must_be_valid_iden(var_name.as_str()); + } else { + // Reads the value expression to advance the parse stream. + // Some parameters do not have any value, + // so ignoring an error occurred here. + let _: Option = meta.value().and_then(|v| v.parse()).ok(); + } + Ok(()) + }) + }) + .expect("something something"); + quote! { Self::#var_ident => write!(s, "{}", #var_name).unwrap() } + }) + .collect(); + + let match_arms: TokenStream = quote! { #(#match_pair),* }; + + let prepare = if all_valid { + quote! { + fn prepare(&self, s: &mut dyn ::std::fmt::Write, q: sea_orm::sea_query::Quote) { + write!(s, "{}", q.left()).unwrap(); + self.unquoted(s); + write!(s, "{}", q.right()).unwrap(); + } + } + } else { + quote! {} + }; + + quote! { + impl sea_orm::sea_query::Iden for #ident { + #prepare + + fn unquoted(&self, s: &mut dyn ::std::fmt::Write) { + match self { + #match_arms + }; + } + } + } +} + +pub fn expand_derive_iden(input: DeriveInput) -> syn::Result { + let DeriveInput { ident, data, .. } = input; + + let mut new_iden: TokenStream = ident.to_string().to_snake_case().parse().unwrap(); + // let new_iden = &v.ident.to_string().to_snake_case(); + input + .attrs + .iter() + .filter(|attr| attr.path().is_ident("sea_orm")) + .try_for_each(|attr| { + attr.parse_nested_meta(|meta| { + if meta.path.is_ident("iden") { + let litstr: LitStr = meta.value()?.parse()?; + new_iden = syn::parse_str::(&litstr.value())?; + } else { + // Reads the value expression to advance the parse stream. + // Some parameters do not have any value, + // so ignoring an error occurred here. + let _: Option = meta.value().and_then(|v| v.parse()).ok(); + } + Ok(()) + }) + })?; + + // Currently we only support enums and unit structs + match data { + syn::Data::Enum(DataEnum { variants, .. }) => { + if variants.is_empty() { + Ok(TokenStream::new()) + } else { + Ok(impl_iden_for_enum(&ident, variants)) + } + } + syn::Data::Struct(DataStruct { + fields: Fields::Unit, + .. + }) => Ok(impl_iden_for_unit_struct( + &ident, + new_iden.to_string().as_str(), + )), + _ => Ok(quote_spanned! { + ident.span() => compile_error!("you can only derive DeriveIden on unit struct or enum"); + }), + } +} diff --git a/sea-orm-macros/src/derives/iden.rs b/sea-orm-macros/src/derives/iden.rs deleted file mode 100644 index ca8b390b4..000000000 --- a/sea-orm-macros/src/derives/iden.rs +++ /dev/null @@ -1,150 +0,0 @@ -use std::convert::{TryFrom, TryInto}; - -use heck::ToSnakeCase; -use proc_macro2::{self, TokenStream, Ident}; -use quote::{quote, quote_spanned}; -use syn::{parse_macro_input, Attribute, DataEnum, DataStruct, DeriveInput, Fields, Variant, Error, Expr, LitStr}; - - -fn must_be_valid_iden(name: &str) -> bool { - // can only begin with [a-z_] - name.chars() - .take(1) - .all(|c| c == '_' || c.is_ascii_alphabetic()) - && name.chars().all(|c| c == '_' || c.is_ascii_alphanumeric()) -} - -fn impl_iden_for_unit_struct( - ident: &proc_macro2::Ident, - table_name: &str, -) -> proc_macro2::TokenStream { - let prepare = if must_be_valid_iden(table_name) { - quote! { - fn prepare(&self, s: &mut dyn ::std::fmt::Write, q: sea_query::Quote) { - write!(s, "{}", q.left()).unwrap(); - self.unquoted(s); - write!(s, "{}", q.right()).unwrap(); - } - } - } else { - quote! {} - }; - quote! { - impl sea_query::Iden for #ident { - #prepare - - fn unquoted(&self, s: &mut dyn ::std::fmt::Write) { - write!(s, #table_name).unwrap(); - } - } - } -} - -fn try_from((table_name, value): (&'a str, &'a Variant)) -> Result { - let Variant { - ident, - fields, - attrs, - .. - } = value; - let attr = find_attr(attrs).map(IdenAttr::try_from).transpose()?; - - Self::new(ident, fields, table_name, attr) -} - -fn impl_iden_for_enum<'a, T>( - ident: &proc_macro2::Ident, - table_name: &str, - variants: T, -) -> proc_macro2::TokenStream -where - T: Iterator, -{ - let mut is_all_valid = true; - - let match_arms = match variants - .map(|v| (table_name, v)) - .map(|v| { - let v = try_from(v)?; - is_all_valid &= v.must_be_valid_iden(); - Ok(v) - }) - .collect::>>() - { - Ok(v) => quote! { #(#v),* }, - Err(e) => return e.to_compile_error(), - }; - - let prepare = if is_all_valid { - quote! { - fn prepare(&self, s: &mut dyn ::std::fmt::Write, q: sea_query::Quote) { - write!(s, "{}", q.left()).unwrap(); - self.unquoted(s); - write!(s, "{}", q.right()).unwrap(); - } - } - } else { - quote! {} - }; - - quote! { - impl sea_query::Iden for #ident { - #prepare - - fn unquoted(&self, s: &mut dyn ::std::fmt::Write) { - match self { - #match_arms - }; - } - } - } -} - -pub fn expand_derive_iden(input: DeriveInput) -> syn::Result { - let DeriveInput { - ident, data, attrs, .. - } = input; - - let table_name = ident.to_string(); - - let mut new_name: TokenStream = quote!(); - input - .attrs - .iter() - .filter(|attr| attr.path().is_ident("sea_orm")) - .try_for_each(|attr| { - attr.parse_nested_meta(|meta| { - if meta.path.is_ident("iden") { - let litstr: LitStr = meta.value()?.parse()?; - new_name = syn::parse_str::(&litstr.value()).expect("iden attribute should contain something"); - } else { - // Reads the value expression to advance the parse stream. - // Some parameters do not have any value, - // so ignoring an error occurred here. - let _: Option = meta.value().and_then(|v| v.parse()).ok(); - } - Ok(()) - }) - })?; - - // Currently we only support enums and unit structs - let variants = - match data { - syn::Data::Enum(DataEnum { variants, .. }) => variants, - syn::Data::Struct(DataStruct { - fields: Fields::Unit, - .. - }) => return impl_iden_for_unit_struct(&ident, &table_name).into(), - _ => return Ok(quote_spanned! { - ident.span() => compile_error!("you can only derive DeriveIden on unit struct or enum"); - }) - }; - - if variants.is_empty() { - return variants; //todo : find good error - } - - let output = impl_iden_for_enum(&ident, &table_name, variants.iter()); - - Ok(output) -} \ No newline at end of file diff --git a/sea-orm-macros/src/derives/mod.rs b/sea-orm-macros/src/derives/mod.rs index 982dc064f..dfc976b69 100644 --- a/sea-orm-macros/src/derives/mod.rs +++ b/sea-orm-macros/src/derives/mod.rs @@ -3,6 +3,7 @@ mod active_model; mod active_model_behavior; mod attributes; mod column; +mod derive_iden; mod entity; mod entity_model; mod from_query_result; @@ -15,12 +16,12 @@ mod related_entity; mod relation; mod try_getable_from_json; mod util; -mod iden; pub use active_enum::*; pub use active_model::*; pub use active_model_behavior::*; pub use column::*; +pub use derive_iden::*; pub use entity::*; pub use entity_model::*; pub use from_query_result::*; @@ -32,4 +33,3 @@ pub use primary_key::*; pub use related_entity::*; pub use relation::*; pub use try_getable_from_json::*; -pub use iden::*; \ No newline at end of file diff --git a/sea-orm-macros/src/lib.rs b/sea-orm-macros/src/lib.rs index 32ac72f7a..772452b66 100644 --- a/sea-orm-macros/src/lib.rs +++ b/sea-orm-macros/src/lib.rs @@ -833,18 +833,46 @@ pub fn enum_iter(input: TokenStream) -> TokenStream { .into() } - -// #[proc_macro_derive(Iden, attributes(iden, method))] -// pub fn iden(input: TokenStream) -> TokenStream { -// let input = parse_macro_input!(input as DeriveInput); -// if cfg!(feature = "sea-query"){ -// crate::derive_iden(input) -// } -// else { -// sea_orm::derive_iden(input) -// } -// } - +/// The DeriveIden derive macro will implement `sea_orm::sea_query::Iden` for simplify Iden implementation. +/// +/// ## Usage +/// +/// ```rust +/// use pretty_assertions::assert_eq; +/// use sea_orm::{DeriveIden, Iden}; +/// +/// #[derive(DeriveIden)] +/// pub enum Class { +/// Id, +/// Title, +/// Text, +/// } +/// assert_eq!(Class::Id.to_string(), "id"); +/// assert_eq!(Class::Title.to_string(), "title"); +/// assert_eq!(Class::Text.to_string(), "text"); +/// +/// #[derive(Iden)] +/// struct Glyph; +/// assert_eq!(Glyph.to_string(), "glyph"); +/// ``` +/// +/// You can use iden = "" to customize the name +/// ``` +/// use pretty_assertions::assert_eq; +/// use sea_orm::{DeriveIden, Iden}; +/// +/// #[derive(DeriveIden)] +/// pub enum Class { +/// Id, +/// #[sea_orm(iden = "turtle")] +/// Title, +/// #[sea_orm(iden = "TeXt")] +/// Text, +/// } +/// assert_eq!(Class::Id.to_string(), "id"); +/// assert_eq!(Class::Title.to_string(), "turtle"); +/// assert_eq!(Class::Text.to_string(), "te_xt"); +/// ``` #[cfg(feature = "derive")] #[proc_macro_derive(DeriveIden, attributes(sea_orm))] pub fn derive_iden(input: TokenStream) -> TokenStream { @@ -854,4 +882,4 @@ pub fn derive_iden(input: TokenStream) -> TokenStream { Ok(token_stream) => token_stream.into(), Err(e) => e.to_compile_error().into(), } -} \ No newline at end of file +} diff --git a/src/lib.rs b/src/lib.rs index f4034da72..d9a358d26 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -349,15 +349,13 @@ pub use schema::*; #[cfg(feature = "macros")] pub use sea_orm_macros::{ DeriveActiveEnum, DeriveActiveModel, DeriveActiveModelBehavior, DeriveColumn, - DeriveCustomColumn, DeriveEntity, DeriveEntityModel, DeriveIntoActiveModel, + DeriveCustomColumn, DeriveEntity, DeriveEntityModel, DeriveIden, DeriveIntoActiveModel, DeriveMigrationName, DeriveModel, DerivePartialModel, DerivePrimaryKey, DeriveRelatedEntity, DeriveRelation, FromJsonQueryResult, FromQueryResult, }; pub use sea_query; pub use sea_query::Iden; -// #[cfg(feature = "macros")] -// pub use sea_query::Iden as DeriveIden; pub use sea_orm_macros::EnumIter; pub use strum; diff --git a/tests/derive_iden.rs b/tests/derive_iden.rs new file mode 100644 index 000000000..7d856b6d0 --- /dev/null +++ b/tests/derive_iden.rs @@ -0,0 +1,37 @@ +pub mod common; +pub use common::{features::*, setup::*, TestContext}; +use sea_orm::entity::prelude::*; +use sea_orm_macros::DeriveIden; + +#[derive(DeriveIden)] +pub enum Class { + Id, + Title, + Text, +} + +#[derive(DeriveIden)] +struct Glyph; + +#[derive(DeriveIden)] +pub enum Book { + Id, + #[sea_orm(iden = "turtle")] + Title, + #[sea_orm(iden = "TeXt")] + Text, +} + +#[sea_orm_macros::test] +async fn main() -> Result<(), DbErr> { + assert_eq!(Class::Id.to_string(), "id"); + assert_eq!(Class::Title.to_string(), "title"); + assert_eq!(Class::Text.to_string(), "text"); + + assert_eq!(Glyph.to_string(), "glyph"); + + assert_eq!(Book::Id.to_string(), "id"); + assert_eq!(Book::Title.to_string(), "turtle"); + assert_eq!(Book::Text.to_string(), "te_xt"); + Ok(()) +} From a71bff41325bbf3c56ca4b6790b751500d92c979 Mon Sep 17 00:00:00 2001 From: Yiu Tin Cheung Ivan Date: Tue, 11 Jul 2023 11:15:30 +0800 Subject: [PATCH 03/11] added feature flag to prevent sea-orm::sea-query::DeriveIden from crashing when sea-query is not used --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 037de27a8..58b87786f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,7 @@ tracing = { version = "0.1", default-features = false, features = ["attributes", rust_decimal = { version = "1", default-features = false, optional = true } bigdecimal = { version = "0.3", default-features = false, optional = true } sea-orm-macros = { version = "0.12.0-rc.4", path = "sea-orm-macros", default-features = false, features = ["strum"] } -sea-query = { version = "0.29.0-rc.2", features = ["thread-safe", "hashable-value"] } +sea-query = { version = "0.29.0-rc.2", features = ["thread-safe", "hashable-value", "sea-orm"] } sea-query-binder = { version = "0.4.0-rc.2", default-features = false, optional = true } strum = { version = "0.24", default-features = false } serde = { version = "1.0", default-features = false } From 6d02efd2afab30e8b88355a80a90c849e4f31046 Mon Sep 17 00:00:00 2001 From: Yiu Tin Cheung Ivan Date: Tue, 11 Jul 2023 11:54:53 +0800 Subject: [PATCH 04/11] fixed doc test and adjusted test case --- sea-orm-macros/src/lib.rs | 15 +++------------ tests/{derive_iden.rs => derive_iden_tests.rs} | 4 ++-- 2 files changed, 5 insertions(+), 14 deletions(-) rename tests/{derive_iden.rs => derive_iden_tests.rs} (91%) diff --git a/sea-orm-macros/src/lib.rs b/sea-orm-macros/src/lib.rs index 53c18c034..85a9fee62 100644 --- a/sea-orm-macros/src/lib.rs +++ b/sea-orm-macros/src/lib.rs @@ -858,8 +858,7 @@ pub fn derive_active_enum_display(input: TokenStream) -> TokenStream { /// ## Usage /// /// ```rust -/// use pretty_assertions::assert_eq; -/// use sea_orm::{DeriveIden, Iden}; +/// use sea_orm::DeriveIden; /// /// #[derive(DeriveIden)] /// pub enum Class { @@ -867,19 +866,14 @@ pub fn derive_active_enum_display(input: TokenStream) -> TokenStream { /// Title, /// Text, /// } -/// assert_eq!(Class::Id.to_string(), "id"); -/// assert_eq!(Class::Title.to_string(), "title"); -/// assert_eq!(Class::Text.to_string(), "text"); /// -/// #[derive(Iden)] +/// #[derive(DeriveIden)] /// struct Glyph; -/// assert_eq!(Glyph.to_string(), "glyph"); /// ``` /// /// You can use iden = "" to customize the name /// ``` -/// use pretty_assertions::assert_eq; -/// use sea_orm::{DeriveIden, Iden}; +/// use sea_orm::DeriveIden; /// /// #[derive(DeriveIden)] /// pub enum Class { @@ -889,9 +883,6 @@ pub fn derive_active_enum_display(input: TokenStream) -> TokenStream { /// #[sea_orm(iden = "TeXt")] /// Text, /// } -/// assert_eq!(Class::Id.to_string(), "id"); -/// assert_eq!(Class::Title.to_string(), "turtle"); -/// assert_eq!(Class::Text.to_string(), "te_xt"); /// ``` #[cfg(feature = "derive")] #[proc_macro_derive(DeriveIden, attributes(sea_orm))] diff --git a/tests/derive_iden.rs b/tests/derive_iden_tests.rs similarity index 91% rename from tests/derive_iden.rs rename to tests/derive_iden_tests.rs index 7d856b6d0..41b1ba4c7 100644 --- a/tests/derive_iden.rs +++ b/tests/derive_iden_tests.rs @@ -22,8 +22,8 @@ pub enum Book { Text, } -#[sea_orm_macros::test] -async fn main() -> Result<(), DbErr> { +#[test] +fn main() -> Result<(), DbErr> { assert_eq!(Class::Id.to_string(), "id"); assert_eq!(Class::Title.to_string(), "title"); assert_eq!(Class::Text.to_string(), "text"); From 8124fb97cd1504e87064280c5bc7e8b4b372efc6 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Tue, 11 Jul 2023 17:56:33 +0800 Subject: [PATCH 05/11] enable `sea-query-derive`'s `sea-orm` feature --- Cargo.toml | 7 ++++--- issues/1473/Cargo.toml | 13 +++++++++++++ issues/1473/src/main.rs | 17 +++++++++++++++++ src/entity/column.rs | 2 +- 4 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 issues/1473/Cargo.toml create mode 100644 issues/1473/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index 58b87786f..d8298bec7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,8 +34,9 @@ tracing = { version = "0.1", default-features = false, features = ["attributes", rust_decimal = { version = "1", default-features = false, optional = true } bigdecimal = { version = "0.3", default-features = false, optional = true } sea-orm-macros = { version = "0.12.0-rc.4", path = "sea-orm-macros", default-features = false, features = ["strum"] } -sea-query = { version = "0.29.0-rc.2", features = ["thread-safe", "hashable-value", "sea-orm"] } -sea-query-binder = { version = "0.4.0-rc.2", default-features = false, optional = true } +sea-query = { version = "0.29.0", git = "https://github.com/darkmmon/sea-query", branch = "sea-orm-feature", features = ["thread-safe", "hashable-value"] } +sea-query-derive = { version = "0.3.0", git = "https://github.com/darkmmon/sea-query", branch = "sea-orm-feature", default-features = false, optional = true } +sea-query-binder = { version = "0.4.0", git = "https://github.com/darkmmon/sea-query", branch = "sea-orm-feature", default-features = false, optional = true } strum = { version = "0.24", default-features = false } serde = { version = "1.0", default-features = false } serde_json = { version = "1.0", default-features = false, optional = true } @@ -74,7 +75,7 @@ default = [ "with-uuid", "with-time", ] -macros = ["sea-orm-macros/derive", "sea-query/derive"] +macros = ["sea-orm-macros/derive", "sea-query/derive", "sea-query-derive/sea-orm"] mock = [] with-json = ["serde_json", "sea-query/with-json", "chrono?/serde", "time?/serde", "uuid?/serde", "sea-query-binder?/with-json", "sqlx?/json"] with-chrono = ["chrono", "sea-query/with-chrono", "sea-query-binder?/with-chrono", "sqlx?/chrono"] diff --git a/issues/1473/Cargo.toml b/issues/1473/Cargo.toml new file mode 100644 index 000000000..ae5bdae57 --- /dev/null +++ b/issues/1473/Cargo.toml @@ -0,0 +1,13 @@ +[workspace] +# A separate workspace + +[package] +name = "sea-orm-issues-1473" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies.sea-orm] +path = "../../" +default-features = false +features = ["macros", "runtime-tokio-native-tls"] diff --git a/issues/1473/src/main.rs b/issues/1473/src/main.rs new file mode 100644 index 000000000..951b165d2 --- /dev/null +++ b/issues/1473/src/main.rs @@ -0,0 +1,17 @@ +use sea_orm::Iden; + +#[derive(Iden)] +enum Character { + Table, + Id, +} + +#[derive(Iden)] +struct Glyph; + +fn main() { + assert_eq!(Character::Table.to_string(), "character"); + assert_eq!(Character::Id.to_string(), "id"); + + assert_eq!(Glyph.to_string(), "glyph"); +} diff --git a/src/entity/column.rs b/src/entity/column.rs index e2ade89b5..b85bcb612 100644 --- a/src/entity/column.rs +++ b/src/entity/column.rs @@ -1,4 +1,4 @@ -use crate::{EntityName, IdenStatic, IntoSimpleExpr, Iterable}; +use crate::{self as sea_orm, EntityName, IdenStatic, IntoSimpleExpr, Iterable}; use sea_query::{ Alias, BinOper, DynIden, Expr, Iden, IntoIden, SeaRc, SelectStatement, SimpleExpr, Value, }; From 9cdfeccc54d6d63abe444ad3cc10006150abb2b5 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Tue, 11 Jul 2023 18:10:10 +0800 Subject: [PATCH 06/11] Bump `sea-query-derive` to v0.4 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index d8298bec7..664878a00 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,7 +35,7 @@ rust_decimal = { version = "1", default-features = false, optional = true } bigdecimal = { version = "0.3", default-features = false, optional = true } sea-orm-macros = { version = "0.12.0-rc.4", path = "sea-orm-macros", default-features = false, features = ["strum"] } sea-query = { version = "0.29.0", git = "https://github.com/darkmmon/sea-query", branch = "sea-orm-feature", features = ["thread-safe", "hashable-value"] } -sea-query-derive = { version = "0.3.0", git = "https://github.com/darkmmon/sea-query", branch = "sea-orm-feature", default-features = false, optional = true } +sea-query-derive = { version = "0.4.0", git = "https://github.com/darkmmon/sea-query", branch = "sea-orm-feature", default-features = false, optional = true } sea-query-binder = { version = "0.4.0", git = "https://github.com/darkmmon/sea-query", branch = "sea-orm-feature", default-features = false, optional = true } strum = { version = "0.24", default-features = false } serde = { version = "1.0", default-features = false } From c34d5559f3343d4af4df7da6ff04360c4f6ec969 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Wed, 12 Jul 2023 18:50:54 +0800 Subject: [PATCH 07/11] Update Cargo.toml --- Cargo.toml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 664878a00..6f2e7f755 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,9 +34,8 @@ tracing = { version = "0.1", default-features = false, features = ["attributes", rust_decimal = { version = "1", default-features = false, optional = true } bigdecimal = { version = "0.3", default-features = false, optional = true } sea-orm-macros = { version = "0.12.0-rc.4", path = "sea-orm-macros", default-features = false, features = ["strum"] } -sea-query = { version = "0.29.0", git = "https://github.com/darkmmon/sea-query", branch = "sea-orm-feature", features = ["thread-safe", "hashable-value"] } -sea-query-derive = { version = "0.4.0", git = "https://github.com/darkmmon/sea-query", branch = "sea-orm-feature", default-features = false, optional = true } -sea-query-binder = { version = "0.4.0", git = "https://github.com/darkmmon/sea-query", branch = "sea-orm-feature", default-features = false, optional = true } +sea-query = { version = "0.29.0", features = ["thread-safe", "hashable-value"] } +sea-query-derive = { version = "0.3.1", optional = true } strum = { version = "0.24", default-features = false } serde = { version = "1.0", default-features = false } serde_json = { version = "1.0", default-features = false, optional = true } From 384b3d01a9b45a1fc9a97db262edb54abbb52420 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Wed, 12 Jul 2023 18:56:06 +0800 Subject: [PATCH 08/11] Update Cargo.toml --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 6f2e7f755..db9fe5298 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,7 @@ bigdecimal = { version = "0.3", default-features = false, optional = true } sea-orm-macros = { version = "0.12.0-rc.4", path = "sea-orm-macros", default-features = false, features = ["strum"] } sea-query = { version = "0.29.0", features = ["thread-safe", "hashable-value"] } sea-query-derive = { version = "0.3.1", optional = true } +sea-query-binder = { version = "0.4.0-rc.2", default-features = false, optional = true } strum = { version = "0.24", default-features = false } serde = { version = "1.0", default-features = false } serde_json = { version = "1.0", default-features = false, optional = true } From 0c5396c2117dc9e2c047d06ee30572ddfb4168a6 Mon Sep 17 00:00:00 2001 From: Yiu Tin Cheung Ivan Date: Wed, 12 Jul 2023 19:06:14 +0800 Subject: [PATCH 09/11] adjusted test cases and updated so that iden attribute will not be snake cased --- sea-orm-macros/src/derives/derive_iden.rs | 3 +-- tests/derive_iden_tests.rs | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/sea-orm-macros/src/derives/derive_iden.rs b/sea-orm-macros/src/derives/derive_iden.rs index 19307e371..026a97b1c 100644 --- a/sea-orm-macros/src/derives/derive_iden.rs +++ b/sea-orm-macros/src/derives/derive_iden.rs @@ -57,7 +57,7 @@ fn impl_iden_for_enum( attr.parse_nested_meta(|meta| { if meta.path.is_ident("iden") { let litstr: LitStr = meta.value()?.parse()?; - var_name = litstr.value().to_snake_case(); + var_name = litstr.value(); all_valid &= must_be_valid_iden(var_name.as_str()); } else { // Reads the value expression to advance the parse stream. @@ -104,7 +104,6 @@ pub fn expand_derive_iden(input: DeriveInput) -> syn::Result { let DeriveInput { ident, data, .. } = input; let mut new_iden: TokenStream = ident.to_string().to_snake_case().parse().unwrap(); - // let new_iden = &v.ident.to_string().to_snake_case(); input .attrs .iter() diff --git a/tests/derive_iden_tests.rs b/tests/derive_iden_tests.rs index 41b1ba4c7..707a69f1f 100644 --- a/tests/derive_iden_tests.rs +++ b/tests/derive_iden_tests.rs @@ -10,9 +10,6 @@ pub enum Class { Text, } -#[derive(DeriveIden)] -struct Glyph; - #[derive(DeriveIden)] pub enum Book { Id, @@ -20,18 +17,30 @@ pub enum Book { Title, #[sea_orm(iden = "TeXt")] Text, + #[sea_orm(iden = "ty_pe")] + Type, } +#[derive(DeriveIden)] +struct Glyph; + +#[derive(DeriveIden)] +#[sea_orm(iden = "weRd")] +struct Word; + #[test] fn main() -> Result<(), DbErr> { assert_eq!(Class::Id.to_string(), "id"); assert_eq!(Class::Title.to_string(), "title"); assert_eq!(Class::Text.to_string(), "text"); - assert_eq!(Glyph.to_string(), "glyph"); - assert_eq!(Book::Id.to_string(), "id"); assert_eq!(Book::Title.to_string(), "turtle"); - assert_eq!(Book::Text.to_string(), "te_xt"); + assert_eq!(Book::Text.to_string(), "TeXt"); + assert_eq!(Book::Type.to_string(), "ty_pe"); + + assert_eq!(Glyph.to_string(), "glyph"); + + assert_eq!(Word.to_string(), "weRd"); Ok(()) } From 2d225d1fc10bd6ca7d29706f4990b3aac57a4682 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Thu, 13 Jul 2023 16:20:36 +0800 Subject: [PATCH 10/11] Update Cargo.toml --- Cargo.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index db9fe5298..bf77c0e2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,7 +35,6 @@ rust_decimal = { version = "1", default-features = false, optional = true } bigdecimal = { version = "0.3", default-features = false, optional = true } sea-orm-macros = { version = "0.12.0-rc.4", path = "sea-orm-macros", default-features = false, features = ["strum"] } sea-query = { version = "0.29.0", features = ["thread-safe", "hashable-value"] } -sea-query-derive = { version = "0.3.1", optional = true } sea-query-binder = { version = "0.4.0-rc.2", default-features = false, optional = true } strum = { version = "0.24", default-features = false } serde = { version = "1.0", default-features = false } @@ -75,7 +74,7 @@ default = [ "with-uuid", "with-time", ] -macros = ["sea-orm-macros/derive", "sea-query/derive", "sea-query-derive/sea-orm"] +macros = ["sea-orm-macros/derive", "sea-query/derive"] mock = [] with-json = ["serde_json", "sea-query/with-json", "chrono?/serde", "time?/serde", "uuid?/serde", "sea-query-binder?/with-json", "sqlx?/json"] with-chrono = ["chrono", "sea-query/with-chrono", "sea-query-binder?/with-chrono", "sqlx?/chrono"] From e0917f4c4e926cf4fdfb257be589b59f5c69c702 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Thu, 13 Jul 2023 16:21:30 +0800 Subject: [PATCH 11/11] Update main.rs --- issues/1473/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/issues/1473/src/main.rs b/issues/1473/src/main.rs index 951b165d2..ed691b825 100644 --- a/issues/1473/src/main.rs +++ b/issues/1473/src/main.rs @@ -1,4 +1,4 @@ -use sea_orm::Iden; +use sea_orm::{sea_query::{self, Iden}}; #[derive(Iden)] enum Character {