diff --git a/src/query/delete.rs b/src/query/delete.rs new file mode 100644 index 00000000..467a6980 --- /dev/null +++ b/src/query/delete.rs @@ -0,0 +1,217 @@ +use crate::{ + ActiveModelTrait, ColumnTrait, EntityTrait, IntoActiveModel, Iterable, PrimaryKeyToColumn, + QueryFilter, QueryTrait, +}; +use core::marker::PhantomData; +use sea_query::{DeleteStatement, IntoIden}; + +#[derive(Clone, Debug)] +pub struct Delete; + +#[derive(Clone, Debug)] +pub struct DeleteOne +where + A: ActiveModelTrait, +{ + pub(crate) query: DeleteStatement, + pub(crate) model: A, +} + +#[derive(Clone, Debug)] +pub struct DeleteMany +where + E: EntityTrait, +{ + pub(crate) query: DeleteStatement, + pub(crate) entity: PhantomData, +} + +impl Delete { + /// Delete one Model or ActiveModel + /// + /// Model + /// ``` + /// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::PostgresQueryBuilder}; + /// + /// assert_eq!( + /// Delete::one(cake::Model { + /// id: 1, + /// name: "Apple Pie".to_owned(), + /// }) + /// .build(PostgresQueryBuilder) + /// .to_string(), + /// r#"DELETE FROM "cake" WHERE "cake"."id" = 1"#, + /// ); + /// ``` + /// ActiveModel + /// ``` + /// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::PostgresQueryBuilder}; + /// + /// assert_eq!( + /// Delete::one(cake::ActiveModel { + /// id: ActiveValue::set(1), + /// name: ActiveValue::set("Apple Pie".to_owned()), + /// }) + /// .build(PostgresQueryBuilder) + /// .to_string(), + /// r#"DELETE FROM "cake" WHERE "cake"."id" = 1"#, + /// ); + /// ``` + pub fn one(model: M) -> DeleteOne + where + E: EntityTrait, + A: ActiveModelTrait, + M: IntoActiveModel, + { + let myself = DeleteOne { + query: DeleteStatement::new() + .from_table(A::Entity::default().into_iden()) + .to_owned(), + model: model.into_active_model(), + }; + myself.prepare() + } + + /// Delete many ActiveModel + /// + /// ``` + /// use sea_orm::{entity::*, query::*, tests_cfg::fruit, sea_query::{Expr, PostgresQueryBuilder}}; + /// + /// assert_eq!( + /// Delete::many(fruit::Entity) + /// .filter(fruit::Column::Name.contains("Apple")) + /// .build(PostgresQueryBuilder) + /// .to_string(), + /// r#"DELETE FROM "fruit" WHERE "fruit"."name" LIKE '%Apple%'"#, + /// ); + /// ``` + pub fn many(entity: E) -> DeleteMany + where + E: EntityTrait, + { + DeleteMany { + query: DeleteStatement::new() + .from_table(entity.into_iden()) + .to_owned(), + entity: PhantomData, + } + } +} + +impl DeleteOne +where + A: ActiveModelTrait, +{ + pub(crate) fn prepare(mut self) -> Self { + for key in ::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 QueryFilter for DeleteOne +where + A: ActiveModelTrait, +{ + type QueryStatement = DeleteStatement; + + fn query(&mut self) -> &mut DeleteStatement { + &mut self.query + } +} + +impl QueryFilter for DeleteMany +where + E: EntityTrait, +{ + type QueryStatement = DeleteStatement; + + fn query(&mut self) -> &mut DeleteStatement { + &mut self.query + } +} + +impl QueryTrait for DeleteOne +where + A: ActiveModelTrait, +{ + type QueryStatement = DeleteStatement; + + fn query(&mut self) -> &mut DeleteStatement { + &mut self.query + } + + fn as_query(&self) -> &DeleteStatement { + &self.query + } + + fn into_query(self) -> DeleteStatement { + self.query + } +} + +impl QueryTrait for DeleteMany +where + E: EntityTrait, +{ + type QueryStatement = DeleteStatement; + + fn query(&mut self) -> &mut DeleteStatement { + &mut self.query + } + + fn as_query(&self) -> &DeleteStatement { + &self.query + } + + fn into_query(self) -> DeleteStatement { + self.query + } +} + +#[cfg(test)] +mod tests { + use crate::tests_cfg::{cake, fruit}; + use crate::{entity::*, query::*}; + use sea_query::PostgresQueryBuilder; + + #[test] + fn delete_1() { + assert_eq!( + Delete::one(cake::Model { + id: 1, + name: "Apple Pie".to_owned(), + }) + .build(PostgresQueryBuilder) + .to_string(), + r#"DELETE FROM "cake" WHERE "cake"."id" = 1"#, + ); + assert_eq!( + Delete::one(cake::ActiveModel { + id: ActiveValue::set(1), + name: ActiveValue::set("Apple Pie".to_owned()), + }) + .build(PostgresQueryBuilder) + .to_string(), + r#"DELETE FROM "cake" WHERE "cake"."id" = 1"#, + ); + } + + #[test] + fn delete_2() { + assert_eq!( + Delete::many(fruit::Entity) + .filter(fruit::Column::Name.contains("Cheese")) + .build(PostgresQueryBuilder) + .to_string(), + r#"DELETE FROM "fruit" WHERE "fruit"."name" LIKE '%Cheese%'"#, + ); + } +} diff --git a/src/query/mod.rs b/src/query/mod.rs index d04595f6..0a00c89d 100644 --- a/src/query/mod.rs +++ b/src/query/mod.rs @@ -1,4 +1,5 @@ pub(crate) mod combine; +mod delete; mod helper; mod insert; mod join; @@ -10,6 +11,7 @@ mod traits; mod update; // pub use combine::*; +pub use delete::*; pub use helper::*; pub use insert::*; pub use join::*;