From 27bd0445962b74c729c81d41b81bf713e1b24e8e Mon Sep 17 00:00:00 2001 From: Isaiah Gamble <77396670+tsar-boomba@users.noreply.github.com> Date: Mon, 19 Dec 2022 04:41:29 -0500 Subject: [PATCH 1/4] Cli serde skip deserialize for primary key option (#1186) * Add CLI option to skip primary keys with serde Implements: https://github.com/SeaQL/sea-orm/issues/841 * Codegen: fix tests * complete skip_deserialize cli feature * run fmt * fix tests Co-authored-by: witcher --- sea-orm-cli/src/cli.rs | 7 ++ sea-orm-cli/src/commands/generate.rs | 2 + sea-orm-codegen/src/entity/writer.rs | 102 +++++++++++++++--- .../tests/compact_with_serde/cake_both.rs | 1 + .../compact_with_serde/cake_deserialize.rs | 1 + .../tests/expanded_with_serde/cake_both.rs | 1 + .../expanded_with_serde/cake_deserialize.rs | 1 + 7 files changed, 102 insertions(+), 13 deletions(-) diff --git a/sea-orm-cli/src/cli.rs b/sea-orm-cli/src/cli.rs index 1d797aa03..af16e158a 100644 --- a/sea-orm-cli/src/cli.rs +++ b/sea-orm-cli/src/cli.rs @@ -228,6 +228,13 @@ pub enum GenerateSubcommands { help = "Generate index file as `lib.rs` instead of `mod.rs`." )] lib: bool, + + #[clap( + action, + long, + help = "Generate a serde field attribute for the primary keys to skip them during deserialization if they're not present, must also use '--with-serde' 'both' or 'deserialize'" + )] + skip_primary_key_deserialization: bool, }, } diff --git a/sea-orm-cli/src/commands/generate.rs b/sea-orm-cli/src/commands/generate.rs index 8117c852d..1f13b57df 100644 --- a/sea-orm-cli/src/commands/generate.rs +++ b/sea-orm-cli/src/commands/generate.rs @@ -27,6 +27,7 @@ pub async fn run_generate_command( with_copy_enums, date_time_crate, lib, + skip_primary_key_deserialization, } => { if verbose { let _ = tracing_subscriber::fmt() @@ -164,6 +165,7 @@ pub async fn run_generate_command( date_time_crate.into(), schema_name, lib, + 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 6f293fc7d..392afe039 100644 --- a/sea-orm-codegen/src/entity/writer.rs +++ b/sea-orm-codegen/src/entity/writer.rs @@ -43,6 +43,7 @@ pub struct EntityWriterContext { pub(crate) date_time_crate: DateTimeCrate, pub(crate) schema_name: Option, pub(crate) lib: bool, + pub(crate) skip_primary_key_deserialization: bool, } impl WithSerde { @@ -103,6 +104,7 @@ impl EntityWriterContext { date_time_crate: DateTimeCrate, schema_name: Option, lib: bool, + skip_primary_key_deserialization: bool, ) -> Self { Self { expanded_format, @@ -111,6 +113,7 @@ impl EntityWriterContext { date_time_crate, schema_name, lib, + skip_primary_key_deserialization, } } } @@ -139,6 +142,10 @@ impl EntityWriter { .iter() .map(|column| column.get_info(&context.date_time_crate)) .collect::>(); + // use must have serde enabled to use this + let skip_primary_key_deserialization = context.skip_primary_key_deserialization + && (context.with_serde == WithSerde::Both + || context.with_serde == WithSerde::Deserialize); info!("Generating {}", entity_file); for info in column_info.iter() { @@ -153,6 +160,7 @@ impl EntityWriter { &context.with_serde, &context.date_time_crate, &context.schema_name, + skip_primary_key_deserialization, ) } else { Self::gen_compact_code_blocks( @@ -160,6 +168,7 @@ impl EntityWriter { &context.with_serde, &context.date_time_crate, &context.schema_name, + skip_primary_key_deserialization, ) }; Self::write(&mut lines, code_blocks); @@ -259,6 +268,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)); @@ -266,7 +276,12 @@ impl EntityWriter { imports, Self::gen_entity_struct(), Self::gen_impl_entity_name(entity, schema_name), - Self::gen_model_struct(entity, with_serde, date_time_crate), + Self::gen_model_struct( + entity, + with_serde, + date_time_crate, + skip_primary_key_deserialization, + ), Self::gen_column_enum(entity), Self::gen_primary_key_enum(entity), Self::gen_impl_primary_key(entity, date_time_crate), @@ -285,12 +300,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, + ), Self::gen_compact_relation_enum(entity), ]; code_blocks.extend(Self::gen_impl_related(entity)); @@ -378,16 +400,42 @@ impl EntityWriter { entity: &Entity, with_serde: &WithSerde, date_time_crate: &DateTimeCrate, + skip_primary_key_deserialization: bool, ) -> TokenStream { let column_names_snake_case = entity.get_column_names_snake_case(); let column_rs_types = entity.get_column_rs_types(date_time_crate); let if_eq_needed = entity.get_eq_needed(); + let primary_keys: Vec = entity + .primary_keys + .iter() + .map(|pk| pk.name.clone()) + .collect(); + let fields = column_names_snake_case.into_iter().enumerate().fold( + TokenStream::new(), + |tokens, (i, field_name)| { + let field_type = column_rs_types.get(i).unwrap(); + let is_primary_key = primary_keys.contains(&field_name.to_string()); + if is_primary_key && skip_primary_key_deserialization { + quote! { + #tokens + #[serde(skip_deserialization)] + pub #field_name: #field_type, + } + } else { + quote! { + #tokens + pub #field_name: #field_type, + } + } + }, + ); + let extra_derive = with_serde.extra_derive(); quote! { #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel #if_eq_needed #extra_derive)] pub struct Model { - #(pub #column_names_snake_case: #column_rs_types,)* + #fields } } } @@ -566,6 +614,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(); @@ -581,11 +630,12 @@ impl EntityWriter { .iter() .map(|col| { let mut attrs: Punctuated<_, Comma> = Punctuated::new(); + let is_primary_key = primary_keys.contains(&col.name); if !col.is_snake_case_name() { let column_name = &col.name; attrs.push(quote! { column_name = #column_name }); } - if primary_keys.contains(&col.name) { + if is_primary_key { attrs.push(quote! { primary_key }); if !col.auto_increment { attrs.push(quote! { auto_increment = false }); @@ -608,8 +658,15 @@ impl EntityWriter { } ts = quote! { #ts #attr }; } - quote! { - #[sea_orm(#ts)] + if is_primary_key && skip_primary_key_deserialization { + quote! { + #[sea_orm(#ts)] + #[serde(skip_deserialization)] + } + } else { + quote! { + #[sea_orm(#ts)] + } } } else { TokenStream::new() @@ -1260,7 +1317,8 @@ mod tests { entity, &crate::WithSerde::None, &crate::DateTimeCrate::Chrono, - &None + &None, + false, ) .into_iter() .skip(1) @@ -1276,7 +1334,8 @@ mod tests { entity, &crate::WithSerde::None, &crate::DateTimeCrate::Chrono, - &Some("public".to_owned()) + &Some("public".to_owned()), + false, ) .into_iter() .skip(1) @@ -1292,7 +1351,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) @@ -1344,7 +1404,8 @@ mod tests { entity, &crate::WithSerde::None, &crate::DateTimeCrate::Chrono, - &None + &None, + false, ) .into_iter() .skip(1) @@ -1360,7 +1421,8 @@ mod tests { entity, &crate::WithSerde::None, &crate::DateTimeCrate::Chrono, - &Some("public".to_owned()) + &Some("public".to_owned()), + false, ) .into_iter() .skip(1) @@ -1376,7 +1438,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) @@ -1406,6 +1469,7 @@ mod tests { None, ), Box::new(EntityWriter::gen_compact_code_blocks), + false, )?; assert_serde_variant_results( &cake_entity, @@ -1415,6 +1479,7 @@ mod tests { None, ), Box::new(EntityWriter::gen_compact_code_blocks), + false, )?; assert_serde_variant_results( &cake_entity, @@ -1424,6 +1489,7 @@ mod tests { None, ), Box::new(EntityWriter::gen_compact_code_blocks), + false, )?; assert_serde_variant_results( &cake_entity, @@ -1433,6 +1499,7 @@ mod tests { None, ), Box::new(EntityWriter::gen_compact_code_blocks), + false, )?; // Expanded code blocks @@ -1444,6 +1511,7 @@ mod tests { None, ), Box::new(EntityWriter::gen_expanded_code_blocks), + false, )?; assert_serde_variant_results( &cake_entity, @@ -1453,6 +1521,7 @@ mod tests { None, ), Box::new(EntityWriter::gen_expanded_code_blocks), + false, )?; assert_serde_variant_results( &cake_entity, @@ -1462,6 +1531,7 @@ mod tests { None, ), Box::new(EntityWriter::gen_expanded_code_blocks), + false, )?; assert_serde_variant_results( &cake_entity, @@ -1471,6 +1541,7 @@ mod tests { None, ), Box::new(EntityWriter::gen_expanded_code_blocks), + false, )?; Ok(()) @@ -1481,11 +1552,14 @@ 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(); + let skip_primary_key_deserialization = entity_serde_variant.1 == WithSerde::Both + || entity_serde_variant.1 == WithSerde::Deserialize; reader.read_until(b'\n', &mut Vec::new())?; @@ -1496,11 +1570,13 @@ mod tests { } let content = lines.join(""); let expected: TokenStream = content.parse().unwrap(); + println!("{:?}", entity_serde_variant.1); let generated = generator( cake_entity, &entity_serde_variant.1, &DateTimeCrate::Chrono, &entity_serde_variant.2, + skip_primary_key_deserialization, ) .into_iter() .fold(TokenStream::new(), |mut acc, tok| { diff --git a/sea-orm-codegen/tests/compact_with_serde/cake_both.rs b/sea-orm-codegen/tests/compact_with_serde/cake_both.rs index 54d3cd167..874d24aad 100644 --- a/sea-orm-codegen/tests/compact_with_serde/cake_both.rs +++ b/sea-orm-codegen/tests/compact_with_serde/cake_both.rs @@ -7,6 +7,7 @@ use serde::{Deserialize, Serialize}; #[sea_orm(table_name = "cake")] pub struct Model { #[sea_orm(primary_key)] + #[serde(skip_deserialization)] pub id: i32, #[sea_orm(column_type = "Text", nullable)] pub name: Option , diff --git a/sea-orm-codegen/tests/compact_with_serde/cake_deserialize.rs b/sea-orm-codegen/tests/compact_with_serde/cake_deserialize.rs index f11569e4a..e2c789086 100644 --- a/sea-orm-codegen/tests/compact_with_serde/cake_deserialize.rs +++ b/sea-orm-codegen/tests/compact_with_serde/cake_deserialize.rs @@ -7,6 +7,7 @@ use serde::Deserialize; #[sea_orm(table_name = "cake")] pub struct Model { #[sea_orm(primary_key)] + #[serde(skip_deserialization)] pub id: i32, #[sea_orm(column_type = "Text", nullable)] pub name: Option , diff --git a/sea-orm-codegen/tests/expanded_with_serde/cake_both.rs b/sea-orm-codegen/tests/expanded_with_serde/cake_both.rs index 924887b42..d0472a974 100644 --- a/sea-orm-codegen/tests/expanded_with_serde/cake_both.rs +++ b/sea-orm-codegen/tests/expanded_with_serde/cake_both.rs @@ -14,6 +14,7 @@ impl EntityName for Entity { #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Eq, Serialize, Deserialize)] pub struct Model { + #[serde(skip_deserialization)] pub id: i32, pub name: Option , } diff --git a/sea-orm-codegen/tests/expanded_with_serde/cake_deserialize.rs b/sea-orm-codegen/tests/expanded_with_serde/cake_deserialize.rs index 88a7c3a96..378077d83 100644 --- a/sea-orm-codegen/tests/expanded_with_serde/cake_deserialize.rs +++ b/sea-orm-codegen/tests/expanded_with_serde/cake_deserialize.rs @@ -14,6 +14,7 @@ impl EntityName for Entity { #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Eq, Deserialize)] pub struct Model { + #[serde(skip_deserialization)] pub id: i32, pub name: Option , } From 2b66b3e37b8e95d29c4999d7151abd72e8a8c2e5 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Mon, 19 Dec 2022 17:53:51 +0800 Subject: [PATCH 2/4] [cli] should be `#[serde(skip_deserializing)]` --- sea-orm-cli/src/cli.rs | 4 +-- sea-orm-cli/src/commands/generate.rs | 4 +-- sea-orm-codegen/src/entity/writer.rs | 36 +++++++++---------- .../tests/compact_with_serde/cake_both.rs | 2 +- .../compact_with_serde/cake_deserialize.rs | 2 +- .../tests/expanded_with_serde/cake_both.rs | 2 +- .../expanded_with_serde/cake_deserialize.rs | 2 +- 7 files changed, 26 insertions(+), 26 deletions(-) diff --git a/sea-orm-cli/src/cli.rs b/sea-orm-cli/src/cli.rs index af16e158a..cbe564618 100644 --- a/sea-orm-cli/src/cli.rs +++ b/sea-orm-cli/src/cli.rs @@ -232,9 +232,9 @@ pub enum GenerateSubcommands { #[clap( action, long, - help = "Generate a serde field attribute for the primary keys to skip them during deserialization if they're not present, must also use '--with-serde' 'both' or 'deserialize'" + help = "Generate a serde field attribute, '#[serde(skip_deserializing)]', for the primary key fields to skip them during deserialization, this flag will be affective only when '--with-serde' is 'both' or 'deserialize'" )] - skip_primary_key_deserialization: bool, + skip_deserializing_primary_key: bool, }, } diff --git a/sea-orm-cli/src/commands/generate.rs b/sea-orm-cli/src/commands/generate.rs index 1f13b57df..907081f05 100644 --- a/sea-orm-cli/src/commands/generate.rs +++ b/sea-orm-cli/src/commands/generate.rs @@ -27,7 +27,7 @@ pub async fn run_generate_command( with_copy_enums, date_time_crate, lib, - skip_primary_key_deserialization, + skip_deserializing_primary_key, } => { if verbose { let _ = tracing_subscriber::fmt() @@ -165,7 +165,7 @@ pub async fn run_generate_command( date_time_crate.into(), schema_name, lib, - skip_primary_key_deserialization, + skip_deserializing_primary_key, ); 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 392afe039..8e216bec8 100644 --- a/sea-orm-codegen/src/entity/writer.rs +++ b/sea-orm-codegen/src/entity/writer.rs @@ -43,7 +43,7 @@ pub struct EntityWriterContext { pub(crate) date_time_crate: DateTimeCrate, pub(crate) schema_name: Option, pub(crate) lib: bool, - pub(crate) skip_primary_key_deserialization: bool, + pub(crate) skip_deserializing_primary_key: bool, } impl WithSerde { @@ -104,7 +104,7 @@ impl EntityWriterContext { date_time_crate: DateTimeCrate, schema_name: Option, lib: bool, - skip_primary_key_deserialization: bool, + skip_deserializing_primary_key: bool, ) -> Self { Self { expanded_format, @@ -113,7 +113,7 @@ impl EntityWriterContext { date_time_crate, schema_name, lib, - skip_primary_key_deserialization, + skip_deserializing_primary_key, } } } @@ -143,7 +143,7 @@ impl EntityWriter { .map(|column| column.get_info(&context.date_time_crate)) .collect::>(); // use must have serde enabled to use this - let skip_primary_key_deserialization = context.skip_primary_key_deserialization + let skip_deserializing_primary_key = context.skip_deserializing_primary_key && (context.with_serde == WithSerde::Both || context.with_serde == WithSerde::Deserialize); @@ -160,7 +160,7 @@ impl EntityWriter { &context.with_serde, &context.date_time_crate, &context.schema_name, - skip_primary_key_deserialization, + skip_deserializing_primary_key, ) } else { Self::gen_compact_code_blocks( @@ -168,7 +168,7 @@ impl EntityWriter { &context.with_serde, &context.date_time_crate, &context.schema_name, - skip_primary_key_deserialization, + skip_deserializing_primary_key, ) }; Self::write(&mut lines, code_blocks); @@ -268,7 +268,7 @@ impl EntityWriter { with_serde: &WithSerde, date_time_crate: &DateTimeCrate, schema_name: &Option, - skip_primary_key_deserialization: bool, + skip_deserializing_primary_key: bool, ) -> Vec { let mut imports = Self::gen_import(with_serde); imports.extend(Self::gen_import_active_enum(entity)); @@ -280,7 +280,7 @@ impl EntityWriter { entity, with_serde, date_time_crate, - skip_primary_key_deserialization, + skip_deserializing_primary_key, ), Self::gen_column_enum(entity), Self::gen_primary_key_enum(entity), @@ -300,7 +300,7 @@ impl EntityWriter { with_serde: &WithSerde, date_time_crate: &DateTimeCrate, schema_name: &Option, - skip_primary_key_deserialization: bool, + skip_deserializing_primary_key: bool, ) -> Vec { let mut imports = Self::gen_import(with_serde); imports.extend(Self::gen_import_active_enum(entity)); @@ -311,7 +311,7 @@ impl EntityWriter { with_serde, date_time_crate, schema_name, - skip_primary_key_deserialization, + skip_deserializing_primary_key, ), Self::gen_compact_relation_enum(entity), ]; @@ -400,7 +400,7 @@ impl EntityWriter { entity: &Entity, with_serde: &WithSerde, date_time_crate: &DateTimeCrate, - skip_primary_key_deserialization: bool, + skip_deserializing_primary_key: bool, ) -> TokenStream { let column_names_snake_case = entity.get_column_names_snake_case(); let column_rs_types = entity.get_column_rs_types(date_time_crate); @@ -415,10 +415,10 @@ impl EntityWriter { |tokens, (i, field_name)| { let field_type = column_rs_types.get(i).unwrap(); let is_primary_key = primary_keys.contains(&field_name.to_string()); - if is_primary_key && skip_primary_key_deserialization { + if is_primary_key && skip_deserializing_primary_key { quote! { #tokens - #[serde(skip_deserialization)] + #[serde(skip_deserializing)] pub #field_name: #field_type, } } else { @@ -614,7 +614,7 @@ impl EntityWriter { with_serde: &WithSerde, date_time_crate: &DateTimeCrate, schema_name: &Option, - skip_primary_key_deserialization: bool, + skip_deserializing_primary_key: bool, ) -> TokenStream { let table_name = entity.table_name.as_str(); let column_names_snake_case = entity.get_column_names_snake_case(); @@ -658,10 +658,10 @@ impl EntityWriter { } ts = quote! { #ts #attr }; } - if is_primary_key && skip_primary_key_deserialization { + if is_primary_key && skip_deserializing_primary_key { quote! { #[sea_orm(#ts)] - #[serde(skip_deserialization)] + #[serde(skip_deserializing)] } } else { quote! { @@ -1558,7 +1558,7 @@ mod tests { ) -> io::Result<()> { let mut reader = BufReader::new(entity_serde_variant.0.as_bytes()); let mut lines: Vec = Vec::new(); - let skip_primary_key_deserialization = entity_serde_variant.1 == WithSerde::Both + let skip_deserializing_primary_key = entity_serde_variant.1 == WithSerde::Both || entity_serde_variant.1 == WithSerde::Deserialize; reader.read_until(b'\n', &mut Vec::new())?; @@ -1576,7 +1576,7 @@ mod tests { &entity_serde_variant.1, &DateTimeCrate::Chrono, &entity_serde_variant.2, - skip_primary_key_deserialization, + skip_deserializing_primary_key, ) .into_iter() .fold(TokenStream::new(), |mut acc, tok| { diff --git a/sea-orm-codegen/tests/compact_with_serde/cake_both.rs b/sea-orm-codegen/tests/compact_with_serde/cake_both.rs index 874d24aad..fa893a5c2 100644 --- a/sea-orm-codegen/tests/compact_with_serde/cake_both.rs +++ b/sea-orm-codegen/tests/compact_with_serde/cake_both.rs @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize}; #[sea_orm(table_name = "cake")] pub struct Model { #[sea_orm(primary_key)] - #[serde(skip_deserialization)] + #[serde(skip_deserializing)] pub id: i32, #[sea_orm(column_type = "Text", nullable)] pub name: Option , diff --git a/sea-orm-codegen/tests/compact_with_serde/cake_deserialize.rs b/sea-orm-codegen/tests/compact_with_serde/cake_deserialize.rs index e2c789086..620bdf67a 100644 --- a/sea-orm-codegen/tests/compact_with_serde/cake_deserialize.rs +++ b/sea-orm-codegen/tests/compact_with_serde/cake_deserialize.rs @@ -7,7 +7,7 @@ use serde::Deserialize; #[sea_orm(table_name = "cake")] pub struct Model { #[sea_orm(primary_key)] - #[serde(skip_deserialization)] + #[serde(skip_deserializing)] pub id: i32, #[sea_orm(column_type = "Text", nullable)] pub name: Option , diff --git a/sea-orm-codegen/tests/expanded_with_serde/cake_both.rs b/sea-orm-codegen/tests/expanded_with_serde/cake_both.rs index d0472a974..40c9e9987 100644 --- a/sea-orm-codegen/tests/expanded_with_serde/cake_both.rs +++ b/sea-orm-codegen/tests/expanded_with_serde/cake_both.rs @@ -14,7 +14,7 @@ impl EntityName for Entity { #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Eq, Serialize, Deserialize)] pub struct Model { - #[serde(skip_deserialization)] + #[serde(skip_deserializing)] pub id: i32, pub name: Option , } diff --git a/sea-orm-codegen/tests/expanded_with_serde/cake_deserialize.rs b/sea-orm-codegen/tests/expanded_with_serde/cake_deserialize.rs index 378077d83..ec2010733 100644 --- a/sea-orm-codegen/tests/expanded_with_serde/cake_deserialize.rs +++ b/sea-orm-codegen/tests/expanded_with_serde/cake_deserialize.rs @@ -14,7 +14,7 @@ impl EntityName for Entity { #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Eq, Deserialize)] pub struct Model { - #[serde(skip_deserialization)] + #[serde(skip_deserializing)] pub id: i32, pub name: Option , } From 73fbd9541dc05b0cde4a6a7f0c1f14bc75f86b55 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Mon, 19 Dec 2022 18:48:19 +0800 Subject: [PATCH 3/4] [CLI] code refactor --- sea-orm-codegen/src/entity/base_entity.rs | 13 +++++ sea-orm-codegen/src/entity/column.rs | 12 +++++ sea-orm-codegen/src/entity/writer.rs | 63 ++++++----------------- 3 files changed, 40 insertions(+), 48 deletions(-) diff --git a/sea-orm-codegen/src/entity/base_entity.rs b/sea-orm-codegen/src/entity/base_entity.rs index 628ef638f..6d96d4273 100644 --- a/sea-orm-codegen/src/entity/base_entity.rs +++ b/sea-orm-codegen/src/entity/base_entity.rs @@ -166,6 +166,19 @@ impl Entity { // if exist, return nothing .map_or(quote! {, Eq}, |_| quote! {}) } + + pub fn get_skip_serde_deserializing( + &self, + skip_deserializing_primary_key: bool, + ) -> Vec { + self.columns + .iter() + .map(|col| { + let is_primary_key = self.primary_keys.iter().any(|pk| pk.name == col.name); + col.get_skip_serde_deserializing(is_primary_key, skip_deserializing_primary_key) + }) + .collect() + } } #[cfg(test)] diff --git a/sea-orm-codegen/src/entity/column.rs b/sea-orm-codegen/src/entity/column.rs index 298176f41..250d9f0ca 100644 --- a/sea-orm-codegen/src/entity/column.rs +++ b/sea-orm-codegen/src/entity/column.rs @@ -211,6 +211,18 @@ impl Column { } info } + + pub fn get_skip_serde_deserializing( + &self, + is_primary_key: bool, + skip_deserializing_primary_key: bool, + ) -> TokenStream { + if skip_deserializing_primary_key && is_primary_key { + quote! { #[serde(skip_deserializing)] } + } else { + quote! {} + } + } } impl From for Column { diff --git a/sea-orm-codegen/src/entity/writer.rs b/sea-orm-codegen/src/entity/writer.rs index 8e216bec8..cb2c15a91 100644 --- a/sea-orm-codegen/src/entity/writer.rs +++ b/sea-orm-codegen/src/entity/writer.rs @@ -405,37 +405,17 @@ impl EntityWriter { let column_names_snake_case = entity.get_column_names_snake_case(); let column_rs_types = entity.get_column_rs_types(date_time_crate); let if_eq_needed = entity.get_eq_needed(); - let primary_keys: Vec = entity - .primary_keys - .iter() - .map(|pk| pk.name.clone()) - .collect(); - let fields = column_names_snake_case.into_iter().enumerate().fold( - TokenStream::new(), - |tokens, (i, field_name)| { - let field_type = column_rs_types.get(i).unwrap(); - let is_primary_key = primary_keys.contains(&field_name.to_string()); - if is_primary_key && skip_deserializing_primary_key { - quote! { - #tokens - #[serde(skip_deserializing)] - pub #field_name: #field_type, - } - } else { - quote! { - #tokens - pub #field_name: #field_type, - } - } - }, - ); - + let skip_serde_deserializing = + entity.get_skip_serde_deserializing(skip_deserializing_primary_key); let extra_derive = with_serde.extra_derive(); quote! { #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel #if_eq_needed #extra_derive)] pub struct Model { - #fields + #( + #skip_serde_deserializing + pub #column_names_snake_case: #column_rs_types, + )* } } } @@ -650,27 +630,23 @@ impl EntityWriter { if col.unique { attrs.push(quote! { unique }); } + let mut ts = quote! {}; if !attrs.is_empty() { - let mut ts = TokenStream::new(); for (i, attr) in attrs.into_iter().enumerate() { if i > 0 { ts = quote! { #ts, }; } ts = quote! { #ts #attr }; } - if is_primary_key && skip_deserializing_primary_key { - quote! { - #[sea_orm(#ts)] - #[serde(skip_deserializing)] - } - } else { - quote! { - #[sea_orm(#ts)] - } - } - } else { - TokenStream::new() + ts = quote! { #[sea_orm(#ts)] }; } + let skip_serde_deserializing = col + .get_skip_serde_deserializing(is_primary_key, skip_deserializing_primary_key); + ts = quote! { + #ts + #skip_serde_deserializing + }; + ts }) .collect(); let schema_name = match Self::gen_schema_name(schema_name) { @@ -1469,7 +1445,6 @@ mod tests { None, ), Box::new(EntityWriter::gen_compact_code_blocks), - false, )?; assert_serde_variant_results( &cake_entity, @@ -1479,7 +1454,6 @@ mod tests { None, ), Box::new(EntityWriter::gen_compact_code_blocks), - false, )?; assert_serde_variant_results( &cake_entity, @@ -1489,7 +1463,6 @@ mod tests { None, ), Box::new(EntityWriter::gen_compact_code_blocks), - false, )?; assert_serde_variant_results( &cake_entity, @@ -1499,7 +1472,6 @@ mod tests { None, ), Box::new(EntityWriter::gen_compact_code_blocks), - false, )?; // Expanded code blocks @@ -1511,7 +1483,6 @@ mod tests { None, ), Box::new(EntityWriter::gen_expanded_code_blocks), - false, )?; assert_serde_variant_results( &cake_entity, @@ -1521,7 +1492,6 @@ mod tests { None, ), Box::new(EntityWriter::gen_expanded_code_blocks), - false, )?; assert_serde_variant_results( &cake_entity, @@ -1531,7 +1501,6 @@ mod tests { None, ), Box::new(EntityWriter::gen_expanded_code_blocks), - false, )?; assert_serde_variant_results( &cake_entity, @@ -1541,7 +1510,6 @@ mod tests { None, ), Box::new(EntityWriter::gen_expanded_code_blocks), - false, )?; Ok(()) @@ -1554,7 +1522,6 @@ mod tests { generator: Box< 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(); From 6618ba979303ff25a155bc0b1cbf0ca275d88016 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Mon, 19 Dec 2022 21:58:50 +0800 Subject: [PATCH 4/4] [cli] rename --- sea-orm-cli/src/cli.rs | 2 +- sea-orm-cli/src/commands/generate.rs | 4 +-- sea-orm-codegen/src/entity/base_entity.rs | 9 +++-- sea-orm-codegen/src/entity/column.rs | 6 ++-- sea-orm-codegen/src/entity/writer.rs | 43 ++++++++++++----------- 5 files changed, 35 insertions(+), 29 deletions(-) diff --git a/sea-orm-cli/src/cli.rs b/sea-orm-cli/src/cli.rs index cbe564618..f7983f9f0 100644 --- a/sea-orm-cli/src/cli.rs +++ b/sea-orm-cli/src/cli.rs @@ -234,7 +234,7 @@ pub enum GenerateSubcommands { long, help = "Generate a serde field attribute, '#[serde(skip_deserializing)]', for the primary key fields to skip them during deserialization, this flag will be affective only when '--with-serde' is 'both' or 'deserialize'" )] - skip_deserializing_primary_key: bool, + serde_skip_deserializing_primary_key: bool, }, } diff --git a/sea-orm-cli/src/commands/generate.rs b/sea-orm-cli/src/commands/generate.rs index 907081f05..43756a776 100644 --- a/sea-orm-cli/src/commands/generate.rs +++ b/sea-orm-cli/src/commands/generate.rs @@ -27,7 +27,7 @@ pub async fn run_generate_command( with_copy_enums, date_time_crate, lib, - skip_deserializing_primary_key, + serde_skip_deserializing_primary_key, } => { if verbose { let _ = tracing_subscriber::fmt() @@ -165,7 +165,7 @@ pub async fn run_generate_command( date_time_crate.into(), schema_name, lib, - skip_deserializing_primary_key, + serde_skip_deserializing_primary_key, ); let output = EntityTransformer::transform(table_stmts)?.generate(&writer_context); diff --git a/sea-orm-codegen/src/entity/base_entity.rs b/sea-orm-codegen/src/entity/base_entity.rs index 6d96d4273..403657ba5 100644 --- a/sea-orm-codegen/src/entity/base_entity.rs +++ b/sea-orm-codegen/src/entity/base_entity.rs @@ -167,15 +167,18 @@ impl Entity { .map_or(quote! {, Eq}, |_| quote! {}) } - pub fn get_skip_serde_deserializing( + pub fn get_serde_skip_deserializing( &self, - skip_deserializing_primary_key: bool, + serde_skip_deserializing_primary_key: bool, ) -> Vec { self.columns .iter() .map(|col| { let is_primary_key = self.primary_keys.iter().any(|pk| pk.name == col.name); - col.get_skip_serde_deserializing(is_primary_key, skip_deserializing_primary_key) + col.get_serde_skip_deserializing( + is_primary_key, + serde_skip_deserializing_primary_key, + ) }) .collect() } diff --git a/sea-orm-codegen/src/entity/column.rs b/sea-orm-codegen/src/entity/column.rs index 250d9f0ca..73d57283b 100644 --- a/sea-orm-codegen/src/entity/column.rs +++ b/sea-orm-codegen/src/entity/column.rs @@ -212,12 +212,12 @@ impl Column { info } - pub fn get_skip_serde_deserializing( + pub fn get_serde_skip_deserializing( &self, is_primary_key: bool, - skip_deserializing_primary_key: bool, + serde_skip_deserializing_primary_key: bool, ) -> TokenStream { - if skip_deserializing_primary_key && is_primary_key { + if serde_skip_deserializing_primary_key && is_primary_key { quote! { #[serde(skip_deserializing)] } } else { quote! {} diff --git a/sea-orm-codegen/src/entity/writer.rs b/sea-orm-codegen/src/entity/writer.rs index cb2c15a91..c5de8245b 100644 --- a/sea-orm-codegen/src/entity/writer.rs +++ b/sea-orm-codegen/src/entity/writer.rs @@ -43,7 +43,7 @@ pub struct EntityWriterContext { pub(crate) date_time_crate: DateTimeCrate, pub(crate) schema_name: Option, pub(crate) lib: bool, - pub(crate) skip_deserializing_primary_key: bool, + pub(crate) serde_skip_deserializing_primary_key: bool, } impl WithSerde { @@ -104,7 +104,7 @@ impl EntityWriterContext { date_time_crate: DateTimeCrate, schema_name: Option, lib: bool, - skip_deserializing_primary_key: bool, + serde_skip_deserializing_primary_key: bool, ) -> Self { Self { expanded_format, @@ -113,7 +113,7 @@ impl EntityWriterContext { date_time_crate, schema_name, lib, - skip_deserializing_primary_key, + serde_skip_deserializing_primary_key, } } } @@ -143,7 +143,8 @@ impl EntityWriter { .map(|column| column.get_info(&context.date_time_crate)) .collect::>(); // use must have serde enabled to use this - let skip_deserializing_primary_key = context.skip_deserializing_primary_key + let serde_skip_deserializing_primary_key = context + .serde_skip_deserializing_primary_key && (context.with_serde == WithSerde::Both || context.with_serde == WithSerde::Deserialize); @@ -160,7 +161,7 @@ impl EntityWriter { &context.with_serde, &context.date_time_crate, &context.schema_name, - skip_deserializing_primary_key, + serde_skip_deserializing_primary_key, ) } else { Self::gen_compact_code_blocks( @@ -168,7 +169,7 @@ impl EntityWriter { &context.with_serde, &context.date_time_crate, &context.schema_name, - skip_deserializing_primary_key, + serde_skip_deserializing_primary_key, ) }; Self::write(&mut lines, code_blocks); @@ -268,7 +269,7 @@ impl EntityWriter { with_serde: &WithSerde, date_time_crate: &DateTimeCrate, schema_name: &Option, - skip_deserializing_primary_key: bool, + serde_skip_deserializing_primary_key: bool, ) -> Vec { let mut imports = Self::gen_import(with_serde); imports.extend(Self::gen_import_active_enum(entity)); @@ -280,7 +281,7 @@ impl EntityWriter { entity, with_serde, date_time_crate, - skip_deserializing_primary_key, + serde_skip_deserializing_primary_key, ), Self::gen_column_enum(entity), Self::gen_primary_key_enum(entity), @@ -300,7 +301,7 @@ impl EntityWriter { with_serde: &WithSerde, date_time_crate: &DateTimeCrate, schema_name: &Option, - skip_deserializing_primary_key: bool, + serde_skip_deserializing_primary_key: bool, ) -> Vec { let mut imports = Self::gen_import(with_serde); imports.extend(Self::gen_import_active_enum(entity)); @@ -311,7 +312,7 @@ impl EntityWriter { with_serde, date_time_crate, schema_name, - skip_deserializing_primary_key, + serde_skip_deserializing_primary_key, ), Self::gen_compact_relation_enum(entity), ]; @@ -400,20 +401,20 @@ impl EntityWriter { entity: &Entity, with_serde: &WithSerde, date_time_crate: &DateTimeCrate, - skip_deserializing_primary_key: bool, + serde_skip_deserializing_primary_key: bool, ) -> TokenStream { let column_names_snake_case = entity.get_column_names_snake_case(); let column_rs_types = entity.get_column_rs_types(date_time_crate); let if_eq_needed = entity.get_eq_needed(); - let skip_serde_deserializing = - entity.get_skip_serde_deserializing(skip_deserializing_primary_key); + let serde_skip_deserializing = + entity.get_serde_skip_deserializing(serde_skip_deserializing_primary_key); let extra_derive = with_serde.extra_derive(); quote! { #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel #if_eq_needed #extra_derive)] pub struct Model { #( - #skip_serde_deserializing + #serde_skip_deserializing pub #column_names_snake_case: #column_rs_types, )* } @@ -594,7 +595,7 @@ impl EntityWriter { with_serde: &WithSerde, date_time_crate: &DateTimeCrate, schema_name: &Option, - skip_deserializing_primary_key: bool, + serde_skip_deserializing_primary_key: bool, ) -> TokenStream { let table_name = entity.table_name.as_str(); let column_names_snake_case = entity.get_column_names_snake_case(); @@ -640,11 +641,13 @@ impl EntityWriter { } ts = quote! { #[sea_orm(#ts)] }; } - let skip_serde_deserializing = col - .get_skip_serde_deserializing(is_primary_key, skip_deserializing_primary_key); + let serde_skip_deserializing = col.get_serde_skip_deserializing( + is_primary_key, + serde_skip_deserializing_primary_key, + ); ts = quote! { #ts - #skip_serde_deserializing + #serde_skip_deserializing }; ts }) @@ -1525,7 +1528,7 @@ mod tests { ) -> io::Result<()> { let mut reader = BufReader::new(entity_serde_variant.0.as_bytes()); let mut lines: Vec = Vec::new(); - let skip_deserializing_primary_key = entity_serde_variant.1 == WithSerde::Both + let serde_skip_deserializing_primary_key = entity_serde_variant.1 == WithSerde::Both || entity_serde_variant.1 == WithSerde::Deserialize; reader.read_until(b'\n', &mut Vec::new())?; @@ -1543,7 +1546,7 @@ mod tests { &entity_serde_variant.1, &DateTimeCrate::Chrono, &entity_serde_variant.2, - skip_deserializing_primary_key, + serde_skip_deserializing_primary_key, ) .into_iter() .fold(TokenStream::new(), |mut acc, tok| {