sea_orm/query/
delete.rs

1use crate::{
2    ActiveModelTrait, ActiveValue, ColumnTrait, EntityTrait, IntoActiveModel, Iterable,
3    PrimaryKeyToColumn, QueryFilter, QueryTrait,
4};
5use core::marker::PhantomData;
6use sea_query::DeleteStatement;
7
8/// Defines the structure for a delete operation
9#[derive(Clone, Debug)]
10pub struct Delete;
11
12/// Perform a delete operation on a model
13#[derive(Clone, Debug)]
14pub struct DeleteOne<A>
15where
16    A: ActiveModelTrait,
17{
18    pub(crate) query: DeleteStatement,
19    pub(crate) model: A,
20}
21
22/// Perform a delete operation on multiple models
23#[derive(Clone, Debug)]
24pub struct DeleteMany<E>
25where
26    E: EntityTrait,
27{
28    pub(crate) query: DeleteStatement,
29    pub(crate) entity: PhantomData<E>,
30}
31
32impl Delete {
33    /// Delete one Model or ActiveModel
34    ///
35    /// Model
36    /// ```
37    /// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
38    ///
39    /// assert_eq!(
40    ///     Delete::one(cake::Model {
41    ///         id: 1,
42    ///         name: "Apple Pie".to_owned(),
43    ///     })
44    ///     .build(DbBackend::Postgres)
45    ///     .to_string(),
46    ///     r#"DELETE FROM "cake" WHERE "cake"."id" = 1"#,
47    /// );
48    /// ```
49    /// ActiveModel
50    /// ```
51    /// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
52    ///
53    /// assert_eq!(
54    ///     Delete::one(cake::ActiveModel {
55    ///         id: ActiveValue::set(1),
56    ///         name: ActiveValue::set("Apple Pie".to_owned()),
57    ///     })
58    ///     .build(DbBackend::Postgres)
59    ///     .to_string(),
60    ///     r#"DELETE FROM "cake" WHERE "cake"."id" = 1"#,
61    /// );
62    /// ```
63    pub fn one<E, A, M>(model: M) -> DeleteOne<A>
64    where
65        E: EntityTrait,
66        A: ActiveModelTrait<Entity = E>,
67        M: IntoActiveModel<A>,
68    {
69        let myself = DeleteOne {
70            query: DeleteStatement::new()
71                .from_table(A::Entity::default().table_ref())
72                .to_owned(),
73            model: model.into_active_model(),
74        };
75        myself.prepare()
76    }
77
78    /// Delete many ActiveModel
79    ///
80    /// ```
81    /// use sea_orm::{entity::*, query::*, tests_cfg::fruit, DbBackend};
82    ///
83    /// assert_eq!(
84    ///     Delete::many(fruit::Entity)
85    ///         .filter(fruit::Column::Name.contains("Apple"))
86    ///         .build(DbBackend::Postgres)
87    ///         .to_string(),
88    ///     r#"DELETE FROM "fruit" WHERE "fruit"."name" LIKE '%Apple%'"#,
89    /// );
90    /// ```
91    pub fn many<E>(entity: E) -> DeleteMany<E>
92    where
93        E: EntityTrait,
94    {
95        DeleteMany {
96            query: DeleteStatement::new()
97                .from_table(entity.table_ref())
98                .to_owned(),
99            entity: PhantomData,
100        }
101    }
102}
103
104impl<A> DeleteOne<A>
105where
106    A: ActiveModelTrait,
107{
108    pub(crate) fn prepare(mut self) -> Self {
109        for key in <A::Entity as EntityTrait>::PrimaryKey::iter() {
110            let col = key.into_column();
111            let av = self.model.get(col);
112            match av {
113                ActiveValue::Set(value) | ActiveValue::Unchanged(value) => {
114                    self = self.filter(col.eq(value));
115                }
116                ActiveValue::NotSet => panic!("PrimaryKey is not set"),
117            }
118        }
119        self
120    }
121}
122
123impl<A> QueryFilter for DeleteOne<A>
124where
125    A: ActiveModelTrait,
126{
127    type QueryStatement = DeleteStatement;
128
129    fn query(&mut self) -> &mut DeleteStatement {
130        &mut self.query
131    }
132}
133
134impl<E> QueryFilter for DeleteMany<E>
135where
136    E: EntityTrait,
137{
138    type QueryStatement = DeleteStatement;
139
140    fn query(&mut self) -> &mut DeleteStatement {
141        &mut self.query
142    }
143}
144
145impl<A> QueryTrait for DeleteOne<A>
146where
147    A: ActiveModelTrait,
148{
149    type QueryStatement = DeleteStatement;
150
151    fn query(&mut self) -> &mut DeleteStatement {
152        &mut self.query
153    }
154
155    fn as_query(&self) -> &DeleteStatement {
156        &self.query
157    }
158
159    fn into_query(self) -> DeleteStatement {
160        self.query
161    }
162}
163
164impl<E> QueryTrait for DeleteMany<E>
165where
166    E: EntityTrait,
167{
168    type QueryStatement = DeleteStatement;
169
170    fn query(&mut self) -> &mut DeleteStatement {
171        &mut self.query
172    }
173
174    fn as_query(&self) -> &DeleteStatement {
175        &self.query
176    }
177
178    fn into_query(self) -> DeleteStatement {
179        self.query
180    }
181}
182
183#[cfg(test)]
184mod tests {
185    use crate::tests_cfg::{cake, fruit};
186    use crate::{entity::*, query::*, DbBackend};
187
188    #[test]
189    fn delete_1() {
190        assert_eq!(
191            Delete::one(cake::Model {
192                id: 1,
193                name: "Apple Pie".to_owned(),
194            })
195            .build(DbBackend::Postgres)
196            .to_string(),
197            r#"DELETE FROM "cake" WHERE "cake"."id" = 1"#,
198        );
199        assert_eq!(
200            Delete::one(cake::ActiveModel {
201                id: ActiveValue::set(1),
202                name: ActiveValue::set("Apple Pie".to_owned()),
203            })
204            .build(DbBackend::Postgres)
205            .to_string(),
206            r#"DELETE FROM "cake" WHERE "cake"."id" = 1"#,
207        );
208    }
209
210    #[test]
211    fn delete_2() {
212        assert_eq!(
213            Delete::many(fruit::Entity)
214                .filter(fruit::Column::Name.contains("Cheese"))
215                .build(DbBackend::Postgres)
216                .to_string(),
217            r#"DELETE FROM "fruit" WHERE "fruit"."name" LIKE '%Cheese%'"#,
218        );
219    }
220}