diff --git a/sea-orm-macros/src/derives/active_model.rs b/sea-orm-macros/src/derives/active_model.rs index 16e09f2a..3a96860e 100644 --- a/sea-orm-macros/src/derives/active_model.rs +++ b/sea-orm-macros/src/derives/active_model.rs @@ -1,3 +1,4 @@ +use crate::util::field_not_ignored; use heck::CamelCase; use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote, quote_spanned}; @@ -14,7 +15,9 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result compile_error!("you can only derive DeriveActiveModel on structs"); }) } - }; + } + .into_iter() + .filter(field_not_ignored); let field: Vec = fields .clone() diff --git a/sea-orm-macros/src/derives/entity_model.rs b/sea-orm-macros/src/derives/entity_model.rs index 66c5725f..768d3b7c 100644 --- a/sea-orm-macros/src/derives/entity_model.rs +++ b/sea-orm-macros/src/derives/entity_model.rs @@ -68,6 +68,7 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec) -> syn::Res let mut default_value = None; let mut default_expr = None; let mut indexed = false; + let mut ignore = false; let mut unique = false; let mut sql_type = None; // search for #[sea_orm(primary_key, auto_increment = false, column_type = "String(Some(255))", default_value = "new user", default_expr = "gen_random_uuid()", nullable, indexed, unique)] @@ -120,7 +121,10 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec) -> syn::Res } Meta::Path(p) => { if let Some(name) = p.get_ident() { - if name == "primary_key" { + if name == "ignore" { + ignore = true; + break; + } else if name == "primary_key" { primary_keys.push(quote! { #field_name }); primary_key_types.push(field.ty.clone()); } else if name == "nullable" { @@ -138,6 +142,11 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec) -> syn::Res } } + if ignore { + columns_enum.pop(); + continue; + } + let field_type = match sql_type { Some(t) => t, None => { diff --git a/sea-orm-macros/src/derives/model.rs b/sea-orm-macros/src/derives/model.rs index 669dbe9e..9d619991 100644 --- a/sea-orm-macros/src/derives/model.rs +++ b/sea-orm-macros/src/derives/model.rs @@ -1,8 +1,9 @@ -use crate::attributes::derive_attr; +use crate::{attributes::derive_attr, util::field_not_ignored}; use heck::CamelCase; use proc_macro2::TokenStream; use quote::{format_ident, quote, quote_spanned}; use std::iter::FromIterator; +use syn::Ident; enum Error { InputNotStruct, @@ -14,6 +15,7 @@ struct DeriveModel { entity_ident: syn::Ident, field_idents: Vec, ident: syn::Ident, + ignore_attrs: Vec, } impl DeriveModel { @@ -48,11 +50,17 @@ impl DeriveModel { }) .collect(); + let ignore_attrs = fields + .iter() + .map(|field| !field_not_ignored(field)) + .collect(); + Ok(DeriveModel { column_idents, entity_ident, field_idents, ident, + ignore_attrs, }) } @@ -70,23 +78,56 @@ impl DeriveModel { let ident = &self.ident; let field_idents = &self.field_idents; let column_idents = &self.column_idents; + let field_values: Vec = column_idents + .iter() + .zip(&self.ignore_attrs) + .map(|(column_ident, ignore)| { + if *ignore { + quote! { + Default::default() + } + } else { + quote! { + row.try_get(pre, sea_orm::IdenStatic::as_str(&<::Entity as sea_orm::entity::EntityTrait>::Column::#column_ident).into())? + } + } + }) + .collect(); quote!( impl sea_orm::FromQueryResult for #ident { fn from_query_result(row: &sea_orm::QueryResult, pre: &str) -> Result { Ok(Self { - #(#field_idents: row.try_get(pre, sea_orm::IdenStatic::as_str(&<::Entity as sea_orm::entity::EntityTrait>::Column::#column_idents).into())?),* + #(#field_idents: #field_values),* }) } } ) } - fn impl_model_trait(&self) -> TokenStream { + fn impl_model_trait<'a>(&'a self) -> TokenStream { let ident = &self.ident; let entity_ident = &self.entity_ident; - let field_idents = &self.field_idents; - let column_idents = &self.column_idents; + let ignore_attrs = &self.ignore_attrs; + let ignore = |(ident, ignore): (&'a Ident, &bool)| -> Option<&'a Ident> { + if *ignore { + None + } else { + Some(ident) + } + }; + let field_idents: Vec<&Ident> = self + .field_idents + .iter() + .zip(ignore_attrs) + .filter_map(ignore) + .collect(); + let column_idents: Vec<&Ident> = self + .column_idents + .iter() + .zip(ignore_attrs) + .filter_map(ignore) + .collect(); let missing_field_msg = format!("field does not exist on {}", ident); diff --git a/sea-orm-macros/src/lib.rs b/sea-orm-macros/src/lib.rs index 879ad5eb..629c5c18 100644 --- a/sea-orm-macros/src/lib.rs +++ b/sea-orm-macros/src/lib.rs @@ -5,6 +5,7 @@ use syn::{parse_macro_input, DeriveInput, Error}; mod attributes; mod derives; +mod util; #[proc_macro_derive(DeriveEntity, attributes(sea_orm))] pub fn derive_entity(input: TokenStream) -> TokenStream { @@ -73,7 +74,7 @@ pub fn derive_model(input: TokenStream) -> TokenStream { .into() } -#[proc_macro_derive(DeriveActiveModel)] +#[proc_macro_derive(DeriveActiveModel, attributes(sea_orm))] pub fn derive_active_model(input: TokenStream) -> TokenStream { let DeriveInput { ident, data, .. } = parse_macro_input!(input); diff --git a/sea-orm-macros/src/util.rs b/sea-orm-macros/src/util.rs new file mode 100644 index 00000000..7dda1087 --- /dev/null +++ b/sea-orm-macros/src/util.rs @@ -0,0 +1,26 @@ +use syn::{punctuated::Punctuated, token::Comma, Field, Meta}; + +pub(crate) fn field_not_ignored(field: &Field) -> bool { + for attr in field.attrs.iter() { + if let Some(ident) = attr.path.get_ident() { + if ident != "sea_orm" { + continue; + } + } else { + continue; + } + + if let Ok(list) = attr.parse_args_with(Punctuated::::parse_terminated) { + for meta in list.iter() { + if let Meta::Path(path) = meta { + if let Some(name) = path.get_ident() { + if name == "ignore" { + return false; + } + } + } + } + } + } + true +} diff --git a/src/tests_cfg/cake_filling_price.rs b/src/tests_cfg/cake_filling_price.rs index e820ae0f..12779d14 100644 --- a/src/tests_cfg/cake_filling_price.rs +++ b/src/tests_cfg/cake_filling_price.rs @@ -19,6 +19,8 @@ pub struct Model { pub cake_id: i32, pub filling_id: i32, pub price: Decimal, + #[sea_orm(ignore)] + pub ignored_attr: i32, } #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] diff --git a/src/tests_cfg/filling.rs b/src/tests_cfg/filling.rs index 433a89b8..14f7a849 100644 --- a/src/tests_cfg/filling.rs +++ b/src/tests_cfg/filling.rs @@ -9,6 +9,8 @@ pub struct Entity; pub struct Model { pub id: i32, pub name: String, + #[sea_orm(ignore)] + pub ignored_attr: i32, } // If your column names are not in snake-case, derive `DeriveCustomColumn` here.