diff --git a/sea-orm-macros/src/derives/active_model.rs b/sea-orm-macros/src/derives/active_model.rs index 374270aa..17c6c50c 100644 --- a/sea-orm-macros/src/derives/active_model.rs +++ b/sea-orm-macros/src/derives/active_model.rs @@ -33,7 +33,7 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result),* + #(pub #field: sea_orm::ActiveValue<#ty>),* } impl sea_orm::ActiveModelOf for ActiveModel {} @@ -41,7 +41,7 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result for ActiveModel { fn from(m: #ident) -> Self { Self { - #(#field: sea_orm::Action::Set(m.#field)),* + #(#field: sea_orm::ActiveValue::set(m.#field)),* } } } @@ -49,27 +49,27 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result sea_orm::Action { + fn take(&mut self, c: Self::Column) -> sea_orm::ActiveValue { match c { - #(Self::Column::#name => std::mem::take(&mut self.#field).into_action_value()),* + #(Self::Column::#name => std::mem::take(&mut self.#field).into_wrapped_value()),* } } - fn get(&self, c: Self::Column) -> sea_orm::Action { + fn get(&self, c: Self::Column) -> sea_orm::ActiveValue { match c { - #(Self::Column::#name => self.#field.clone().into_action_value()),* + #(Self::Column::#name => self.#field.clone().into_wrapped_value()),* } } fn set(&mut self, c: Self::Column, v: sea_orm::Value) { match c { - #(Self::Column::#name => self.#field = sea_orm::Action::Set(v.unwrap())),* + #(Self::Column::#name => self.#field = sea_orm::ActiveValue::set(v.unwrap())),* } } fn unset(&mut self, c: Self::Column) { match c { - #(Self::Column::#name => self.#field = sea_orm::Action::Unset),* + #(Self::Column::#name => self.#field = sea_orm::ActiveValue::unset()),* } } } diff --git a/src/entity/active_model.rs b/src/entity/active_model.rs index c0e87bf8..50b5461d 100644 --- a/src/entity/active_model.rs +++ b/src/entity/active_model.rs @@ -1,26 +1,75 @@ use crate::{ColumnTrait, EntityTrait, Value}; use std::fmt::Debug; +#[derive(Clone, Debug, Default)] +pub struct ActiveValue +where + V: Default, +{ + value: V, + state: ActiveValueState, +} + #[derive(Clone, Debug)] -pub enum Action { - Set(V), +pub enum ActiveValueState { + Set, Unset, } -impl Default for Action { +impl Default for ActiveValueState { fn default() -> Self { Self::Unset } } -impl Action +impl ActiveValue where - V: Into, + V: Default, { - pub fn into_action_value(self) -> Action { - match self { - Self::Set(v) => Action::Set(v.into()), - Self::Unset => Action::Unset, + pub fn set(value: V) -> Self { + Self { + value, + state: ActiveValueState::Set, + } + } + + pub fn is_set(&self) -> bool { + matches!(self.state, ActiveValueState::Set) + } + + pub fn unset() -> Self { + Self { + value: V::default(), + state: ActiveValueState::Unset, + } + } + + pub fn is_unset(&self) -> bool { + matches!(self.state, ActiveValueState::Unset) + } + + pub fn take(&mut self) -> V { + self.state = ActiveValueState::Unset; + std::mem::take(&mut self.value) + } + + pub fn unwrap(self) -> V { + self.value + } +} + +impl ActiveValue +where + V: Default + Into, +{ + pub fn into_value(self) -> Value { + self.value.into() + } + + pub fn into_wrapped_value(self) -> ActiveValue { + match self.state { + ActiveValueState::Set => ActiveValue::set(self.into_value()), + ActiveValueState::Unset => ActiveValue::unset(), } } } @@ -34,9 +83,9 @@ where pub trait ActiveModelTrait: Clone + Debug { type Column: ColumnTrait; - fn take(&mut self, c: Self::Column) -> Action; + fn take(&mut self, c: Self::Column) -> ActiveValue; - fn get(&self, c: Self::Column) -> Action; + fn get(&self, c: Self::Column) -> ActiveValue; fn set(&mut self, c: Self::Column, v: Value); diff --git a/src/entity/prelude.rs b/src/entity/prelude.rs index f131f167..1482a509 100644 --- a/src/entity/prelude.rs +++ b/src/entity/prelude.rs @@ -1,6 +1,6 @@ pub use crate::{ - Action, ActiveModelOf, ActiveModelTrait, ColumnTrait, ColumnType, DeriveActiveModel, - DeriveColumn, DeriveEntity, DeriveModel, DerivePrimaryKey, EntityName, EntityTrait, EnumIter, - Iden, IdenStatic, ModelTrait, PrimaryKeyOfModel, PrimaryKeyTrait, QueryResult, Related, - RelationDef, RelationTrait, Select, TypeErr, Value, + ActiveModelOf, ActiveModelTrait, ColumnTrait, ColumnType, DeriveActiveModel, DeriveColumn, + DeriveEntity, DeriveModel, DerivePrimaryKey, EntityName, EntityTrait, EnumIter, Iden, + IdenStatic, ModelTrait, PrimaryKeyOfModel, PrimaryKeyTrait, QueryResult, Related, RelationDef, + RelationTrait, Select, TypeErr, Value, }; diff --git a/src/operation/insert.rs b/src/operation/insert.rs index 7adf40d9..5dfeb19c 100644 --- a/src/operation/insert.rs +++ b/src/operation/insert.rs @@ -1,4 +1,4 @@ -use crate::{Action, ActiveModelOf, ActiveModelTrait, EntityTrait, Iterable, Statement}; +use crate::{ActiveModelOf, ActiveModelTrait, EntityTrait, Iterable, Statement}; use core::marker::PhantomData; use sea_query::{InsertStatement, IntoIden, QueryBuilder}; @@ -36,9 +36,10 @@ where let mut columns = Vec::new(); let mut values = Vec::new(); for col in A::Column::iter() { - if let Action::Set(val) = am.take(col) { + let av = am.take(col); + if av.is_set() { columns.push(col); - values.push(val); + values.push(av.into_value()); } } self.query.columns(columns); @@ -73,7 +74,7 @@ where #[cfg(test)] mod tests { use crate::tests_cfg::cake; - use crate::{Action, Insert}; + use crate::{ActiveValue, Insert}; use sea_query::PostgresQueryBuilder; #[test] @@ -81,8 +82,8 @@ mod tests { assert_eq!( Insert::::new() .one(cake::ActiveModel { - id: Action::Unset, - name: Action::Set("Apple Pie".to_owned()), + id: ActiveValue::unset(), + name: ActiveValue::set("Apple Pie".to_owned()), }) .build(PostgresQueryBuilder) .to_string(), @@ -95,8 +96,8 @@ mod tests { assert_eq!( Insert::::new() .one(cake::ActiveModel { - id: Action::Set(1), - name: Action::Set("Apple Pie".to_owned()), + id: ActiveValue::set(1), + name: ActiveValue::set("Apple Pie".to_owned()), }) .build(PostgresQueryBuilder) .to_string(),