ActiveValue

This commit is contained in:
Chris Tsang 2021-05-28 13:09:31 +08:00
parent d3ee74cbe5
commit b1afd5da3e
4 changed files with 81 additions and 31 deletions

View File

@ -33,7 +33,7 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result<Token
Ok(quote!( Ok(quote!(
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct ActiveModel { pub struct ActiveModel {
#(pub #field: sea_orm::Action<#ty>),* #(pub #field: sea_orm::ActiveValue<#ty>),*
} }
impl sea_orm::ActiveModelOf<Entity> for ActiveModel {} impl sea_orm::ActiveModelOf<Entity> for ActiveModel {}
@ -41,7 +41,7 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result<Token
impl From<#ident> for ActiveModel { impl From<#ident> for ActiveModel {
fn from(m: #ident) -> Self { fn from(m: #ident) -> Self {
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<Token
impl sea_orm::ActiveModelTrait for ActiveModel { impl sea_orm::ActiveModelTrait for ActiveModel {
type Column = Column; type Column = Column;
fn take(&mut self, c: Self::Column) -> sea_orm::Action<sea_orm::Value> { fn take(&mut self, c: Self::Column) -> sea_orm::ActiveValue<sea_orm::Value> {
match c { 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<sea_orm::Value> { fn get(&self, c: Self::Column) -> sea_orm::ActiveValue<sea_orm::Value> {
match c { 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) { fn set(&mut self, c: Self::Column, v: sea_orm::Value) {
match c { 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) { fn unset(&mut self, c: Self::Column) {
match c { match c {
#(Self::Column::#name => self.#field = sea_orm::Action::Unset),* #(Self::Column::#name => self.#field = sea_orm::ActiveValue::unset()),*
} }
} }
} }

View File

@ -1,26 +1,75 @@
use crate::{ColumnTrait, EntityTrait, Value}; use crate::{ColumnTrait, EntityTrait, Value};
use std::fmt::Debug; use std::fmt::Debug;
#[derive(Clone, Debug, Default)]
pub struct ActiveValue<V>
where
V: Default,
{
value: V,
state: ActiveValueState,
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum Action<V> { pub enum ActiveValueState {
Set(V), Set,
Unset, Unset,
} }
impl<V> Default for Action<V> { impl Default for ActiveValueState {
fn default() -> Self { fn default() -> Self {
Self::Unset Self::Unset
} }
} }
impl<V> Action<V> impl<V> ActiveValue<V>
where where
V: Into<Value>, V: Default,
{ {
pub fn into_action_value(self) -> Action<Value> { pub fn set(value: V) -> Self {
match self { Self {
Self::Set(v) => Action::Set(v.into()), value,
Self::Unset => Action::Unset, 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<V> ActiveValue<V>
where
V: Default + Into<Value>,
{
pub fn into_value(self) -> Value {
self.value.into()
}
pub fn into_wrapped_value(self) -> ActiveValue<Value> {
match self.state {
ActiveValueState::Set => ActiveValue::set(self.into_value()),
ActiveValueState::Unset => ActiveValue::unset(),
} }
} }
} }
@ -34,9 +83,9 @@ where
pub trait ActiveModelTrait: Clone + Debug { pub trait ActiveModelTrait: Clone + Debug {
type Column: ColumnTrait; type Column: ColumnTrait;
fn take(&mut self, c: Self::Column) -> Action<Value>; fn take(&mut self, c: Self::Column) -> ActiveValue<Value>;
fn get(&self, c: Self::Column) -> Action<Value>; fn get(&self, c: Self::Column) -> ActiveValue<Value>;
fn set(&mut self, c: Self::Column, v: Value); fn set(&mut self, c: Self::Column, v: Value);

View File

@ -1,6 +1,6 @@
pub use crate::{ pub use crate::{
Action, ActiveModelOf, ActiveModelTrait, ColumnTrait, ColumnType, DeriveActiveModel, ActiveModelOf, ActiveModelTrait, ColumnTrait, ColumnType, DeriveActiveModel, DeriveColumn,
DeriveColumn, DeriveEntity, DeriveModel, DerivePrimaryKey, EntityName, EntityTrait, EnumIter, DeriveEntity, DeriveModel, DerivePrimaryKey, EntityName, EntityTrait, EnumIter, Iden,
Iden, IdenStatic, ModelTrait, PrimaryKeyOfModel, PrimaryKeyTrait, QueryResult, Related, IdenStatic, ModelTrait, PrimaryKeyOfModel, PrimaryKeyTrait, QueryResult, Related, RelationDef,
RelationDef, RelationTrait, Select, TypeErr, Value, RelationTrait, Select, TypeErr, Value,
}; };

View File

@ -1,4 +1,4 @@
use crate::{Action, ActiveModelOf, ActiveModelTrait, EntityTrait, Iterable, Statement}; use crate::{ActiveModelOf, ActiveModelTrait, EntityTrait, Iterable, Statement};
use core::marker::PhantomData; use core::marker::PhantomData;
use sea_query::{InsertStatement, IntoIden, QueryBuilder}; use sea_query::{InsertStatement, IntoIden, QueryBuilder};
@ -36,9 +36,10 @@ where
let mut columns = Vec::new(); let mut columns = Vec::new();
let mut values = Vec::new(); let mut values = Vec::new();
for col in A::Column::iter() { 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); columns.push(col);
values.push(val); values.push(av.into_value());
} }
} }
self.query.columns(columns); self.query.columns(columns);
@ -73,7 +74,7 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::tests_cfg::cake; use crate::tests_cfg::cake;
use crate::{Action, Insert}; use crate::{ActiveValue, Insert};
use sea_query::PostgresQueryBuilder; use sea_query::PostgresQueryBuilder;
#[test] #[test]
@ -81,8 +82,8 @@ mod tests {
assert_eq!( assert_eq!(
Insert::<cake::ActiveModel>::new() Insert::<cake::ActiveModel>::new()
.one(cake::ActiveModel { .one(cake::ActiveModel {
id: Action::Unset, id: ActiveValue::unset(),
name: Action::Set("Apple Pie".to_owned()), name: ActiveValue::set("Apple Pie".to_owned()),
}) })
.build(PostgresQueryBuilder) .build(PostgresQueryBuilder)
.to_string(), .to_string(),
@ -95,8 +96,8 @@ mod tests {
assert_eq!( assert_eq!(
Insert::<cake::ActiveModel>::new() Insert::<cake::ActiveModel>::new()
.one(cake::ActiveModel { .one(cake::ActiveModel {
id: Action::Set(1), id: ActiveValue::set(1),
name: Action::Set("Apple Pie".to_owned()), name: ActiveValue::set("Apple Pie".to_owned()),
}) })
.build(PostgresQueryBuilder) .build(PostgresQueryBuilder)
.to_string(), .to_string(),