diff --git a/src/connector/update.rs b/src/connector/update.rs index fef52268..6ded9b13 100644 --- a/src/connector/update.rs +++ b/src/connector/update.rs @@ -1,4 +1,4 @@ -use crate::{ActiveModelTrait, Connection, Database, ExecErr, Statement, Update}; +use crate::{ActiveModelTrait, Connection, Database, ExecErr, Statement, UpdateOne}; use sea_query::{QueryBuilder, UpdateStatement}; use std::future::Future; @@ -12,7 +12,7 @@ pub struct UpdateResult { pub rows_affected: u64, } -impl<'a, A: 'a> Update +impl<'a, A: 'a> UpdateOne where A: ActiveModelTrait, { diff --git a/src/entity/base.rs b/src/entity/base.rs index f5dbc1f1..98c94ff2 100644 --- a/src/entity/base.rs +++ b/src/entity/base.rs @@ -1,7 +1,7 @@ use crate::{ ActiveModelTrait, ColumnTrait, FromQueryResult, Insert, ModelTrait, OneOrManyActiveModel, PrimaryKeyToColumn, PrimaryKeyTrait, QueryFilter, RelationBuilder, RelationTrait, RelationType, - Select, Update, + Select, Update, UpdateOne, }; use sea_query::{Iden, IntoValueTuple}; use std::fmt::Debug; @@ -211,10 +211,10 @@ pub trait EntityTrait: EntityName { /// r#"UPDATE "fruit" SET "name" = 'Orange' WHERE "fruit"."id" = 1"#, /// ); /// ``` - fn update(model: A) -> Update + fn update(model: A) -> UpdateOne where A: ActiveModelTrait, { - Update::new(model) + Update::one(model) } } diff --git a/src/query/combine.rs b/src/query/combine.rs index b53f3a60..2df02a0f 100644 --- a/src/query/combine.rs +++ b/src/query/combine.rs @@ -70,7 +70,7 @@ where #[cfg(test)] mod tests { use crate::tests_cfg::{cake, fruit}; - use crate::{ColumnTrait, EntityTrait, QueryFilter, QueryTrait, SelectHelper}; + use crate::{ColumnTrait, EntityTrait, QueryFilter, QueryTrait, QuerySelect}; use sea_query::MysqlQueryBuilder; #[test] diff --git a/src/query/update.rs b/src/query/update.rs index f372721b..f03c4a5d 100644 --- a/src/query/update.rs +++ b/src/query/update.rs @@ -2,10 +2,14 @@ use crate::{ ActiveModelTrait, ColumnTrait, EntityTrait, Iterable, PrimaryKeyToColumn, QueryFilter, QueryTrait, }; -use sea_query::{IntoIden, UpdateStatement}; +use sea_query::{IntoIden, SimpleExpr, UpdateStatement}; +use core::marker::PhantomData; #[derive(Clone, Debug)] -pub struct Update +pub struct Update; + +#[derive(Clone, Debug)] +pub struct UpdateOne where A: ActiveModelTrait, { @@ -13,23 +17,47 @@ where pub(crate) model: A, } -impl Update +#[derive(Clone, Debug)] +pub struct UpdateMany where - A: ActiveModelTrait, + E: EntityTrait, { - pub fn new(model: M) -> Self + pub(crate) query: UpdateStatement, + pub(crate) entity: PhantomData, +} + +impl Update { + pub fn one(model: A) -> UpdateOne where - M: Into, + E: EntityTrait, + A: ActiveModelTrait, { - let myself = Self { + let myself = UpdateOne { query: UpdateStatement::new() .table(A::Entity::default().into_iden()) .to_owned(), - model: model.into(), + model, }; myself.prepare() } + pub fn many(entity: E) -> UpdateMany + where + E: EntityTrait, + { + UpdateMany { + query: UpdateStatement::new() + .table(entity.into_iden()) + .to_owned(), + entity: PhantomData, + } + } +} + +impl UpdateOne +where + A: ActiveModelTrait, +{ pub(crate) fn prepare(mut self) -> Self { for key in ::PrimaryKey::iter() { let col = key.into_column(); @@ -53,7 +81,7 @@ where } } -impl QueryFilter for Update +impl QueryFilter for UpdateOne where A: ActiveModelTrait, { @@ -64,7 +92,18 @@ where } } -impl QueryTrait for Update +impl QueryFilter for UpdateMany +where + E: EntityTrait, +{ + type QueryStatement = UpdateStatement; + + fn query(&mut self) -> &mut UpdateStatement { + &mut self.query + } +} + +impl QueryTrait for UpdateOne where A: ActiveModelTrait, { @@ -83,16 +122,48 @@ where } } +impl QueryTrait for UpdateMany +where + E: EntityTrait, +{ + type QueryStatement = UpdateStatement; + + fn query(&mut self) -> &mut UpdateStatement { + &mut self.query + } + + fn as_query(&self) -> &UpdateStatement { + &self.query + } + + fn into_query(self) -> UpdateStatement { + self.query + } +} + +impl UpdateMany +where + E: EntityTrait, +{ + pub fn col_expr(mut self, col: T, expr: SimpleExpr) -> Self + where + T: IntoIden, + { + self.query.col_expr(col, expr); + self + } +} + #[cfg(test)] mod tests { use crate::tests_cfg::{cake, fruit}; - use crate::{ActiveValue, QueryTrait, Update}; - use sea_query::PostgresQueryBuilder; + use crate::{entity::*, query::*}; + use sea_query::{PostgresQueryBuilder, Expr, Value}; #[test] fn update_1() { assert_eq!( - Update::::new(cake::ActiveModel { + Update::one(cake::ActiveModel { id: ActiveValue::set(1), name: ActiveValue::set("Apple Pie".to_owned()), }) @@ -105,7 +176,7 @@ mod tests { #[test] fn update_2() { assert_eq!( - Update::::new(fruit::ActiveModel { + Update::one(fruit::ActiveModel { id: ActiveValue::set(1), name: ActiveValue::set("Orange".to_owned()), cake_id: ActiveValue::unset(), @@ -119,7 +190,7 @@ mod tests { #[test] fn update_3() { assert_eq!( - Update::::new(fruit::ActiveModel { + Update::one(fruit::ActiveModel { id: ActiveValue::set(2), name: ActiveValue::unchanged("Apple".to_owned()), cake_id: ActiveValue::set(Some(3)), @@ -129,4 +200,16 @@ mod tests { r#"UPDATE "fruit" SET "cake_id" = 3 WHERE "fruit"."id" = 2"#, ); } + + #[test] + fn update_4() { + assert_eq!( + Update::many(fruit::Entity) + .col_expr(fruit::Column::CakeId, Expr::value(Value::Null)) + .filter(fruit::Column::Name.contains("Apple")) + .build(PostgresQueryBuilder) + .to_string(), + r#"UPDATE "fruit" SET "cake_id" = NULL WHERE "fruit"."name" LIKE '%Apple%'"#, + ); + } }