diff --git a/sea-orm-cli/src/cli.rs b/sea-orm-cli/src/cli.rs index 5b302396d..191b62513 100644 --- a/sea-orm-cli/src/cli.rs +++ b/sea-orm-cli/src/cli.rs @@ -175,6 +175,13 @@ pub enum GenerateSubcommands { help = "The datetime crate to use for generating entities." )] date_time_crate: DateTimeCrate, + + #[clap( + action, + long, + help = "Generate a serde field attribute for the primary keys to skip them during deserialization if they're not present" + )] + skip_primary_key_deserialization: bool, }, } diff --git a/sea-orm-cli/src/commands.rs b/sea-orm-cli/src/commands.rs index 70b13d010..6d014df44 100644 --- a/sea-orm-cli/src/commands.rs +++ b/sea-orm-cli/src/commands.rs @@ -27,6 +27,7 @@ pub async fn run_generate_command( database_url, with_serde, date_time_crate, + skip_primary_key_deserialization, } => { if verbose { let _ = tracing_subscriber::fmt() @@ -171,6 +172,7 @@ pub async fn run_generate_command( WithSerde::from_str(&with_serde).unwrap(), date_time_crate.into(), schema_name, + skip_primary_key_deserialization, ); let output = EntityTransformer::transform(table_stmts)?.generate(&writer_context); diff --git a/sea-orm-codegen/src/entity/writer.rs b/sea-orm-codegen/src/entity/writer.rs index 446869fb7..f45739d64 100644 --- a/sea-orm-codegen/src/entity/writer.rs +++ b/sea-orm-codegen/src/entity/writer.rs @@ -41,6 +41,7 @@ pub struct EntityWriterContext { pub(crate) with_serde: WithSerde, pub(crate) date_time_crate: DateTimeCrate, pub(crate) schema_name: Option, + pub(crate) skip_primary_key_deserialization: bool, } impl WithSerde { @@ -99,12 +100,14 @@ impl EntityWriterContext { with_serde: WithSerde, date_time_crate: DateTimeCrate, schema_name: Option, + skip_primary_key_deserialization: bool, ) -> Self { Self { expanded_format, with_serde, date_time_crate, schema_name, + skip_primary_key_deserialization, } } } @@ -145,6 +148,7 @@ impl EntityWriter { &context.with_serde, &context.date_time_crate, &context.schema_name, + context.skip_primary_key_deserialization, ) } else { Self::gen_compact_code_blocks( @@ -152,6 +156,7 @@ impl EntityWriter { &context.with_serde, &context.date_time_crate, &context.schema_name, + context.skip_primary_key_deserialization, ) }; Self::write(&mut lines, code_blocks); @@ -241,6 +246,7 @@ impl EntityWriter { with_serde: &WithSerde, date_time_crate: &DateTimeCrate, schema_name: &Option, + _skip_primary_key_deserialization: bool, ) -> Vec { let mut imports = Self::gen_import(with_serde); imports.extend(Self::gen_import_active_enum(entity)); @@ -267,12 +273,19 @@ impl EntityWriter { with_serde: &WithSerde, date_time_crate: &DateTimeCrate, schema_name: &Option, + skip_primary_key_deserialization: bool, ) -> Vec { 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, date_time_crate, schema_name), + Self::gen_compact_model_struct( + entity, + with_serde, + date_time_crate, + schema_name, + skip_primary_key_deserialization, + ), ]; let relation_defs = if entity.get_relation_enum_name().is_empty() { vec![ @@ -553,6 +566,7 @@ impl EntityWriter { with_serde: &WithSerde, date_time_crate: &DateTimeCrate, schema_name: &Option, + skip_primary_key_deserialization: bool, ) -> TokenStream { let table_name = entity.table_name.as_str(); let column_names_snake_case = entity.get_column_names_snake_case(); @@ -567,6 +581,7 @@ impl EntityWriter { .iter() .map(|col| { let mut attrs: Punctuated<_, Comma> = Punctuated::new(); + let mut skip_pk_deserialization = false; if !col.is_snake_case_name() { let column_name = &col.name; attrs.push(quote! { column_name = #column_name }); @@ -576,6 +591,12 @@ impl EntityWriter { if !col.auto_increment { attrs.push(quote! { auto_increment = false }); } + + // if deserialization with serde is even desired, set it to what the user + // wants + if with_serde == &WithSerde::Deserialize || with_serde == &WithSerde::Both { + skip_pk_deserialization = skip_primary_key_deserialization; + } } if let Some(ts) = col.get_col_type_attrs() { attrs.extend(vec![ts]); @@ -594,8 +615,15 @@ impl EntityWriter { } ts = quote! { #ts #attr }; } - quote! { - #[sea_orm(#ts)] + if skip_pk_deserialization { + quote! { + #[sea_orm(#ts)] + #[serde(skip_deserialization)] + } + } else { + quote! { + #[sea_orm(#ts)] + } } } else { TokenStream::new() @@ -1073,7 +1101,8 @@ mod tests { entity, &crate::WithSerde::None, &crate::DateTimeCrate::Chrono, - &None + &None, + false, ) .into_iter() .skip(1) @@ -1089,7 +1118,8 @@ mod tests { entity, &crate::WithSerde::None, &crate::DateTimeCrate::Chrono, - &Some("public".to_owned()) + &Some("public".to_owned()), + false, ) .into_iter() .skip(1) @@ -1105,7 +1135,8 @@ mod tests { entity, &crate::WithSerde::None, &crate::DateTimeCrate::Chrono, - &Some("schema_name".to_owned()) + &Some("schema_name".to_owned()), + false, ) .into_iter() .skip(1) @@ -1149,7 +1180,8 @@ mod tests { entity, &crate::WithSerde::None, &crate::DateTimeCrate::Chrono, - &None + &None, + false, ) .into_iter() .skip(1) @@ -1165,7 +1197,8 @@ mod tests { entity, &crate::WithSerde::None, &crate::DateTimeCrate::Chrono, - &Some("public".to_owned()) + &Some("public".to_owned()), + false, ) .into_iter() .skip(1) @@ -1181,7 +1214,8 @@ mod tests { entity, &crate::WithSerde::None, &crate::DateTimeCrate::Chrono, - &Some("schema_name".to_owned()) + &Some("schema_name".to_owned()), + false, ) .into_iter() .skip(1) @@ -1211,6 +1245,7 @@ mod tests { None, ), Box::new(EntityWriter::gen_compact_code_blocks), + false, )?; assert_serde_variant_results( &cake_entity, @@ -1220,6 +1255,7 @@ mod tests { None, ), Box::new(EntityWriter::gen_compact_code_blocks), + false, )?; assert_serde_variant_results( &cake_entity, @@ -1229,6 +1265,7 @@ mod tests { None, ), Box::new(EntityWriter::gen_compact_code_blocks), + false, )?; assert_serde_variant_results( &cake_entity, @@ -1238,6 +1275,7 @@ mod tests { None, ), Box::new(EntityWriter::gen_compact_code_blocks), + false, )?; // Expanded code blocks @@ -1249,6 +1287,7 @@ mod tests { None, ), Box::new(EntityWriter::gen_expanded_code_blocks), + false, )?; assert_serde_variant_results( &cake_entity, @@ -1258,6 +1297,7 @@ mod tests { None, ), Box::new(EntityWriter::gen_expanded_code_blocks), + false, )?; assert_serde_variant_results( &cake_entity, @@ -1267,6 +1307,7 @@ mod tests { None, ), Box::new(EntityWriter::gen_expanded_code_blocks), + false, )?; assert_serde_variant_results( &cake_entity, @@ -1276,6 +1317,7 @@ mod tests { None, ), Box::new(EntityWriter::gen_expanded_code_blocks), + false, )?; Ok(()) @@ -1286,8 +1328,9 @@ mod tests { cake_entity: &Entity, entity_serde_variant: &(String, WithSerde, Option), generator: Box< - dyn Fn(&Entity, &WithSerde, &DateTimeCrate, &Option) -> Vec, + dyn Fn(&Entity, &WithSerde, &DateTimeCrate, &Option, bool) -> Vec, >, + primary_key_auto_increment: bool, ) -> io::Result<()> { let mut reader = BufReader::new(entity_serde_variant.0.as_bytes()); let mut lines: Vec = Vec::new(); @@ -1306,6 +1349,7 @@ mod tests { &entity_serde_variant.1, &DateTimeCrate::Chrono, &entity_serde_variant.2, + false, ) .into_iter() .fold(TokenStream::new(), |mut acc, tok| {