Change update behavior, add ActiveModel insert & update

This commit is contained in:
Billy Chan 2021-09-07 11:11:23 +08:00 committed by Chris Tsang
parent eca3949ea9
commit f4d1a52791
8 changed files with 43 additions and 24 deletions

View File

@ -98,7 +98,7 @@ let mut pear: fruit::ActiveModel = pear.unwrap().into();
pear.name = Set("Sweet pear".to_owned());
// update one
let pear: fruit::ActiveModel = Fruit::update(pear).exec(db).await?;
let pear: fruit::ActiveModel = pear.update(db).await?;
// update many: UPDATE "fruit" SET "cake_id" = NULL WHERE "fruit"."name" LIKE '%Apple%'
Fruit::update_many()

View File

@ -33,7 +33,7 @@ pub async fn insert_and_update(db: &DbConn) -> Result<(), DbErr> {
let mut pear: fruit::ActiveModel = pear.unwrap().into();
pear.name = Set("Sweet pear".to_owned());
let pear: fruit::ActiveModel = Fruit::update(pear).exec(db).await?;
let pear: fruit::ActiveModel = pear.update(db).await?;
println!();
println!("Updated: {:?}\n", pear);

View File

@ -37,6 +37,14 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result<Token
}
impl ActiveModel {
pub async fn insert(self, db: &sea_orm::DatabaseConnection) -> Result<Self, sea_orm::DbErr> {
sea_orm::insert_and_select_active_model::<Self, Entity>(self, db).await
}
pub async fn update(self, db: &sea_orm::DatabaseConnection) -> Result<Self, sea_orm::DbErr> {
sea_orm::update_active_model::<Self, Entity>(self, db).await
}
pub async fn save(self, db: &sea_orm::DatabaseConnection) -> Result<Self, sea_orm::DbErr> {
sea_orm::save_active_model::<Self, Entity>(self, db).await
}

View File

@ -212,7 +212,10 @@ where
Ok(am)
}
async fn insert_and_select_active_model<A, E>(am: A, db: &DatabaseConnection) -> Result<A, DbErr>
pub async fn insert_and_select_active_model<A, E>(
am: A,
db: &DatabaseConnection,
) -> Result<A, DbErr>
where
A: ActiveModelTrait<Entity = E>,
E::Model: IntoActiveModel<A>,
@ -240,12 +243,12 @@ where
}
}
async fn update_active_model<A, E>(am: A, db: &DatabaseConnection) -> Result<A, DbErr>
pub async fn update_active_model<A, E>(am: A, db: &DatabaseConnection) -> Result<A, DbErr>
where
A: ActiveModelTrait<Entity = E>,
E: EntityTrait,
{
let exec = E::update(am).exec(db);
let exec = E::update(am).prepare_filters().exec(db);
exec.await
}

View File

@ -386,7 +386,7 @@ pub trait EntityTrait: EntityName {
/// # let _: Result<(), DbErr> = smol::block_on(async {
/// #
/// assert_eq!(
/// fruit::Entity::update(orange.clone()).exec(&db).await?, // Clone here because we need to assert_eq
/// orange.clone().update(&db).await?, // Clone here because we need to assert_eq
/// orange
/// );
/// #

View File

@ -126,7 +126,7 @@
//! pear.name = Set("Sweet pear".to_owned());
//!
//! // update one
//! let pear: fruit::ActiveModel = Fruit::update(pear).exec(db).await?;
//! let pear: fruit::ActiveModel = pear.update(db).await?;
//!
//! // update many: UPDATE "fruit" SET "cake_id" = NULL WHERE "fruit"."name" LIKE '%Apple%'
//! Fruit::update_many()

View File

@ -37,6 +37,7 @@ impl Update {
/// id: ActiveValue::set(1),
/// name: ActiveValue::set("Apple Pie".to_owned()),
/// })
/// .filter(cake::Column::Id.eq(1))
/// .build(DbBackend::Postgres)
/// .to_string(),
/// r#"UPDATE "cake" SET "name" = 'Apple Pie' WHERE "cake"."id" = 1"#,
@ -53,7 +54,7 @@ impl Update {
.to_owned(),
model,
};
myself.prepare()
myself.prepare_values()
}
/// Update many ActiveModel
@ -85,16 +86,7 @@ impl<A> UpdateOne<A>
where
A: ActiveModelTrait,
{
pub(crate) fn prepare(mut self) -> Self {
for key in <A::Entity as EntityTrait>::PrimaryKey::iter() {
let col = key.into_column();
let av = self.model.get(col);
if av.is_set() || av.is_unchanged() {
self = self.filter(col.eq(av.unwrap()));
} else {
panic!("PrimaryKey is not set");
}
}
pub(crate) fn prepare_values(mut self) -> Self {
for col in <A::Entity as EntityTrait>::Column::iter() {
if <A::Entity as EntityTrait>::PrimaryKey::from_column(col).is_some() {
continue;
@ -106,6 +98,19 @@ where
}
self
}
pub(crate) fn prepare_filters(mut self) -> Self {
for key in <A::Entity as EntityTrait>::PrimaryKey::iter() {
let col = key.into_column();
let av = self.model.get(col);
if av.is_set() || av.is_unchanged() {
self = self.filter(col.eq(av.unwrap()));
} else {
panic!("PrimaryKey is not set");
}
}
self
}
}
impl<A> QueryFilter for UpdateOne<A>
@ -194,6 +199,7 @@ mod tests {
id: ActiveValue::set(1),
name: ActiveValue::set("Apple Pie".to_owned()),
})
.filter(cake::Column::Id.eq(1))
.build(DbBackend::Postgres)
.to_string(),
r#"UPDATE "cake" SET "name" = 'Apple Pie' WHERE "cake"."id" = 1"#,
@ -208,6 +214,7 @@ mod tests {
name: ActiveValue::set("Orange".to_owned()),
cake_id: ActiveValue::unset(),
})
.filter(fruit::Column::Id.eq(1))
.build(DbBackend::Postgres)
.to_string(),
r#"UPDATE "fruit" SET "name" = 'Orange' WHERE "fruit"."id" = 1"#,
@ -222,6 +229,7 @@ mod tests {
name: ActiveValue::unchanged("Apple".to_owned()),
cake_id: ActiveValue::set(Some(3)),
})
.filter(fruit::Column::Id.eq(2))
.build(DbBackend::Postgres)
.to_string(),
r#"UPDATE "fruit" SET "cake_id" = 3 WHERE "fruit"."id" = 2"#,

View File

@ -42,8 +42,8 @@ pub async fn test_update_cake(db: &DbConn) {
cake_am.name = Set("Extra chocolate mud cake".to_owned());
cake_am.price = Set(dec!(20.00));
let _cake_update_res: cake::ActiveModel = Cake::update(cake_am)
.exec(db)
let _cake_update_res: cake::ActiveModel = cake_am
.update(db)
.await
.expect("could not update cake");
@ -81,8 +81,8 @@ pub async fn test_update_bakery(db: &DbConn) {
bakery_am.name = Set("SeaBreeze Bakery".to_owned());
bakery_am.profit_margin = Set(12.00);
let _bakery_update_res: bakery::ActiveModel = Bakery::update(bakery_am)
.exec(db)
let _bakery_update_res: bakery::ActiveModel = bakery_am
.update(db)
.await
.expect("could not update bakery");
@ -123,8 +123,8 @@ pub async fn test_update_deleted_customer(db: &DbConn) {
..Default::default()
};
let _customer_update_res: customer::ActiveModel = Customer::update(customer)
.exec(db)
let _customer_update_res: customer::ActiveModel = customer
.update(db)
.await
.expect("could not update customer");