From 562201e622f6808183940774a41625a9275be9a7 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Tue, 1 Nov 2022 15:42:13 +0800 Subject: [PATCH 1/4] Unchanged ActiveValue as Set --- sea-orm-macros/src/derives/active_model.rs | 7 + src/entity/active_model.rs | 147 +++++++++++++++++++++ 2 files changed, 154 insertions(+) diff --git a/sea-orm-macros/src/derives/active_model.rs b/sea-orm-macros/src/derives/active_model.rs index 43efe6b6c..e866cc15b 100644 --- a/sea-orm-macros/src/derives/active_model.rs +++ b/sea-orm-macros/src/derives/active_model.rs @@ -154,6 +154,13 @@ fn derive_active_model(all_fields: IntoIter) -> syn::Result #(#field: sea_orm::ActiveValue::not_set()),* } } + + fn val_as_set(&mut self, c: ::Column) { + match c { + #(::Column::#name => self.#field.val_as_set(),)* + _ => panic!("This ActiveModel does not have this field"), + } + } } )) } diff --git a/src/entity/active_model.rs b/src/entity/active_model.rs index 2da20c4a8..b12bb5e27 100644 --- a/src/entity/active_model.rs +++ b/src/entity/active_model.rs @@ -105,6 +105,17 @@ pub trait ActiveModelTrait: Clone + Debug { /// The default implementation of the ActiveModel fn default() -> Self; + /// Set fields of value [ActiveValue::Unchanged] as [ActiveValue::Set] + fn val_as_set(&mut self, c: ::Column); + + /// Set all fields of value [ActiveValue::Unchanged] as [ActiveValue::Set] + fn all_val_as_set(mut self) -> Self { + for col in ::Column::iter() { + self.val_as_set(col); + } + self + } + /// Get the primary key of the ActiveModel #[allow(clippy::question_mark)] fn get_primary_key_value(&self) -> Option { @@ -819,6 +830,14 @@ where Self::NotSet => ActiveValue::not_set(), } } + + /// Convert [ActiveValue::Unchanged] into [ActiveValue::Set] + pub fn val_as_set(&mut self) { + *self = match self.take() { + Some(value) => ActiveValue::Set(value), + None => ActiveValue::NotSet, + }; + } } impl std::convert::AsRef for ActiveValue @@ -1272,4 +1291,132 @@ mod tests { fruit.set(fruit::Column::Name, "apple".into()); assert!(fruit.is_changed()); } + + #[test] + fn test_val_as_set_1() { + assert_eq!( + fruit::Model { + id: 1, + name: "Apple".into(), + cake_id: None, + } + .into_active_model(), + fruit::ActiveModel { + id: Unchanged(1), + name: Unchanged("Apple".into()), + cake_id: Unchanged(None) + }, + ); + + assert_eq!( + fruit::Model { + id: 1, + name: "Apple".into(), + cake_id: None, + } + .into_active_model() + .all_val_as_set(), + fruit::ActiveModel { + id: Set(1), + name: Set("Apple".into()), + cake_id: Set(None) + }, + ); + + assert_eq!( + fruit::Model { + id: 1, + name: "Apple".into(), + cake_id: Some(2), + } + .into_active_model(), + fruit::ActiveModel { + id: Unchanged(1), + name: Unchanged("Apple".into()), + cake_id: Unchanged(Some(2)), + }, + ); + + assert_eq!( + fruit::Model { + id: 1, + name: "Apple".into(), + cake_id: Some(2), + } + .into_active_model() + .all_val_as_set(), + fruit::ActiveModel { + id: Set(1), + name: Set("Apple".into()), + cake_id: Set(Some(2)), + }, + ); + } + + #[smol_potat::test] + async fn test_val_as_set_2() -> Result<(), DbErr> { + use crate::*; + + let db = MockDatabase::new(DbBackend::Postgres) + .append_exec_results(vec![ + MockExecResult { + last_insert_id: 1, + rows_affected: 1, + }, + MockExecResult { + last_insert_id: 1, + rows_affected: 1, + }, + ]) + .append_query_results(vec![ + vec![fruit::Model { + id: 1, + name: "Apple".to_owned(), + cake_id: None, + }], + vec![fruit::Model { + id: 1, + name: "Apple".to_owned(), + cake_id: None, + }], + ]) + .into_connection(); + + fruit::Model { + id: 1, + name: "Apple".into(), + cake_id: None, + } + .into_active_model() + .update(&db) + .await?; + + fruit::Model { + id: 1, + name: "Apple".into(), + cake_id: None, + } + .into_active_model() + .all_val_as_set() + .update(&db) + .await?; + + assert_eq!( + db.into_transaction_log(), + vec![ + Transaction::from_sql_and_values( + DbBackend::Postgres, + r#"UPDATE "fruit" SET WHERE "fruit"."id" = $1 RETURNING "id", "name", "cake_id""#, + vec![1i32.into()], + ), + Transaction::from_sql_and_values( + DbBackend::Postgres, + r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#, + vec!["Apple".into(), Option::::None.into(), 1i32.into()], + ), + ] + ); + + Ok(()) + } } From 7be9178e59516eb1dad4d403d2354ddd4a7242c4 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Thu, 24 Nov 2022 11:21:58 +0800 Subject: [PATCH 2/4] Renaming --- sea-orm-macros/src/derives/active_model.rs | 4 ++-- src/entity/active_model.rs | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sea-orm-macros/src/derives/active_model.rs b/sea-orm-macros/src/derives/active_model.rs index e866cc15b..15fdd776c 100644 --- a/sea-orm-macros/src/derives/active_model.rs +++ b/sea-orm-macros/src/derives/active_model.rs @@ -155,9 +155,9 @@ fn derive_active_model(all_fields: IntoIter) -> syn::Result } } - fn val_as_set(&mut self, c: ::Column) { + fn unchanged_value_into_set(&mut self, c: ::Column) { match c { - #(::Column::#name => self.#field.val_as_set(),)* + #(::Column::#name => self.#field.unchanged_value_into_set(),)* _ => panic!("This ActiveModel does not have this field"), } } diff --git a/src/entity/active_model.rs b/src/entity/active_model.rs index b12bb5e27..5fd9de16c 100644 --- a/src/entity/active_model.rs +++ b/src/entity/active_model.rs @@ -106,12 +106,12 @@ pub trait ActiveModelTrait: Clone + Debug { fn default() -> Self; /// Set fields of value [ActiveValue::Unchanged] as [ActiveValue::Set] - fn val_as_set(&mut self, c: ::Column); + fn unchanged_value_into_set(&mut self, c: ::Column); /// Set all fields of value [ActiveValue::Unchanged] as [ActiveValue::Set] - fn all_val_as_set(mut self) -> Self { + fn all_unchanged_value_into_set(mut self) -> Self { for col in ::Column::iter() { - self.val_as_set(col); + self.unchanged_value_into_set(col); } self } @@ -832,7 +832,7 @@ where } /// Convert [ActiveValue::Unchanged] into [ActiveValue::Set] - pub fn val_as_set(&mut self) { + pub fn unchanged_value_into_set(&mut self) { *self = match self.take() { Some(value) => ActiveValue::Set(value), None => ActiveValue::NotSet, @@ -1293,7 +1293,7 @@ mod tests { } #[test] - fn test_val_as_set_1() { + fn test_unchanged_value_into_set_1() { assert_eq!( fruit::Model { id: 1, @@ -1315,7 +1315,7 @@ mod tests { cake_id: None, } .into_active_model() - .all_val_as_set(), + .all_unchanged_value_into_set(), fruit::ActiveModel { id: Set(1), name: Set("Apple".into()), @@ -1344,7 +1344,7 @@ mod tests { cake_id: Some(2), } .into_active_model() - .all_val_as_set(), + .all_unchanged_value_into_set(), fruit::ActiveModel { id: Set(1), name: Set("Apple".into()), @@ -1354,7 +1354,7 @@ mod tests { } #[smol_potat::test] - async fn test_val_as_set_2() -> Result<(), DbErr> { + async fn test_unchanged_value_into_set_2() -> Result<(), DbErr> { use crate::*; let db = MockDatabase::new(DbBackend::Postgres) @@ -1397,7 +1397,7 @@ mod tests { cake_id: None, } .into_active_model() - .all_val_as_set() + .all_unchanged_value_into_set() .update(&db) .await?; From 88bd12efb998013281432b4b9a9e07cf63988301 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Mon, 28 Nov 2022 16:20:48 +0800 Subject: [PATCH 3/4] Rename --- sea-orm-macros/src/derives/active_model.rs | 4 ++-- src/entity/active_model.rs | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sea-orm-macros/src/derives/active_model.rs b/sea-orm-macros/src/derives/active_model.rs index 15fdd776c..a30e42768 100644 --- a/sea-orm-macros/src/derives/active_model.rs +++ b/sea-orm-macros/src/derives/active_model.rs @@ -155,9 +155,9 @@ fn derive_active_model(all_fields: IntoIter) -> syn::Result } } - fn unchanged_value_into_set(&mut self, c: ::Column) { + fn set_dirty(&mut self, c: ::Column) { match c { - #(::Column::#name => self.#field.unchanged_value_into_set(),)* + #(::Column::#name => self.#field.set_dirty(),)* _ => panic!("This ActiveModel does not have this field"), } } diff --git a/src/entity/active_model.rs b/src/entity/active_model.rs index 5fd9de16c..e7637a085 100644 --- a/src/entity/active_model.rs +++ b/src/entity/active_model.rs @@ -106,12 +106,12 @@ pub trait ActiveModelTrait: Clone + Debug { fn default() -> Self; /// Set fields of value [ActiveValue::Unchanged] as [ActiveValue::Set] - fn unchanged_value_into_set(&mut self, c: ::Column); + fn set_dirty(&mut self, c: ::Column); /// Set all fields of value [ActiveValue::Unchanged] as [ActiveValue::Set] - fn all_unchanged_value_into_set(mut self) -> Self { + fn set_all_dirty(mut self) -> Self { for col in ::Column::iter() { - self.unchanged_value_into_set(col); + self.set_dirty(col); } self } @@ -832,7 +832,7 @@ where } /// Convert [ActiveValue::Unchanged] into [ActiveValue::Set] - pub fn unchanged_value_into_set(&mut self) { + pub fn set_dirty(&mut self) { *self = match self.take() { Some(value) => ActiveValue::Set(value), None => ActiveValue::NotSet, @@ -1293,7 +1293,7 @@ mod tests { } #[test] - fn test_unchanged_value_into_set_1() { + fn test_set_dirty_1() { assert_eq!( fruit::Model { id: 1, @@ -1315,7 +1315,7 @@ mod tests { cake_id: None, } .into_active_model() - .all_unchanged_value_into_set(), + .set_all_dirty(), fruit::ActiveModel { id: Set(1), name: Set("Apple".into()), @@ -1344,7 +1344,7 @@ mod tests { cake_id: Some(2), } .into_active_model() - .all_unchanged_value_into_set(), + .set_all_dirty(), fruit::ActiveModel { id: Set(1), name: Set("Apple".into()), @@ -1354,7 +1354,7 @@ mod tests { } #[smol_potat::test] - async fn test_unchanged_value_into_set_2() -> Result<(), DbErr> { + async fn test_set_dirty_2() -> Result<(), DbErr> { use crate::*; let db = MockDatabase::new(DbBackend::Postgres) @@ -1397,7 +1397,7 @@ mod tests { cake_id: None, } .into_active_model() - .all_unchanged_value_into_set() + .set_all_dirty() .update(&db) .await?; From bfe3f18bb6aa356c6f40d9c70db2489e5979619b Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Wed, 11 Jan 2023 19:53:08 +0800 Subject: [PATCH 4/4] Rename methods --- sea-orm-macros/src/derives/active_model.rs | 4 ++-- src/entity/active_model.rs | 27 ++++++++++++---------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/sea-orm-macros/src/derives/active_model.rs b/sea-orm-macros/src/derives/active_model.rs index a30e42768..5dbba6692 100644 --- a/sea-orm-macros/src/derives/active_model.rs +++ b/sea-orm-macros/src/derives/active_model.rs @@ -155,9 +155,9 @@ fn derive_active_model(all_fields: IntoIter) -> syn::Result } } - fn set_dirty(&mut self, c: ::Column) { + fn reset(&mut self, c: ::Column) { match c { - #(::Column::#name => self.#field.set_dirty(),)* + #(::Column::#name => self.#field.reset(),)* _ => panic!("This ActiveModel does not have this field"), } } diff --git a/src/entity/active_model.rs b/src/entity/active_model.rs index e7637a085..5a6ebda1f 100644 --- a/src/entity/active_model.rs +++ b/src/entity/active_model.rs @@ -105,13 +105,15 @@ pub trait ActiveModelTrait: Clone + Debug { /// The default implementation of the ActiveModel fn default() -> Self; - /// Set fields of value [ActiveValue::Unchanged] as [ActiveValue::Set] - fn set_dirty(&mut self, c: ::Column); + /// Reset the value from [ActiveValue::Unchanged] to [ActiveValue::Set], + /// leaving [ActiveValue::NotSet] untouched. + fn reset(&mut self, c: ::Column); - /// Set all fields of value [ActiveValue::Unchanged] as [ActiveValue::Set] - fn set_all_dirty(mut self) -> Self { + /// Reset all values from [ActiveValue::Unchanged] to [ActiveValue::Set], + /// leaving [ActiveValue::NotSet] untouched. + fn reset_all(mut self) -> Self { for col in ::Column::iter() { - self.set_dirty(col); + self.reset(col); } self } @@ -831,8 +833,9 @@ where } } - /// Convert [ActiveValue::Unchanged] into [ActiveValue::Set] - pub fn set_dirty(&mut self) { + /// Reset the value from [ActiveValue::Unchanged] to [ActiveValue::Set], + /// leaving [ActiveValue::NotSet] untouched. + pub fn reset(&mut self) { *self = match self.take() { Some(value) => ActiveValue::Set(value), None => ActiveValue::NotSet, @@ -1293,7 +1296,7 @@ mod tests { } #[test] - fn test_set_dirty_1() { + fn test_reset_1() { assert_eq!( fruit::Model { id: 1, @@ -1315,7 +1318,7 @@ mod tests { cake_id: None, } .into_active_model() - .set_all_dirty(), + .reset_all(), fruit::ActiveModel { id: Set(1), name: Set("Apple".into()), @@ -1344,7 +1347,7 @@ mod tests { cake_id: Some(2), } .into_active_model() - .set_all_dirty(), + .reset_all(), fruit::ActiveModel { id: Set(1), name: Set("Apple".into()), @@ -1354,7 +1357,7 @@ mod tests { } #[smol_potat::test] - async fn test_set_dirty_2() -> Result<(), DbErr> { + async fn test_reset_2() -> Result<(), DbErr> { use crate::*; let db = MockDatabase::new(DbBackend::Postgres) @@ -1397,7 +1400,7 @@ mod tests { cake_id: None, } .into_active_model() - .set_all_dirty() + .reset_all() .update(&db) .await?;