sea_orm/executor/
delete.rs

1use crate::{
2    error::*, ActiveModelTrait, ColumnTrait, ConnectionTrait, DeleteMany, DeleteOne, EntityTrait,
3    Iterable,
4};
5use sea_query::{DeleteStatement, Query};
6use std::future::Future;
7
8use super::{SelectModel, SelectorRaw};
9
10/// Handles DELETE operations in a ActiveModel using [DeleteStatement]
11#[derive(Clone, Debug)]
12pub struct Deleter {
13    query: DeleteStatement,
14}
15
16/// The result of a DELETE operation
17#[derive(Clone, Debug, PartialEq, Eq)]
18pub struct DeleteResult {
19    /// The number of rows affected by the DELETE operation
20    pub rows_affected: u64,
21}
22
23impl<'a, A: 'a> DeleteOne<A>
24where
25    A: ActiveModelTrait,
26{
27    /// Execute a DELETE operation on one ActiveModel
28    pub fn exec<C>(self, db: &'a C) -> impl Future<Output = Result<DeleteResult, DbErr>> + 'a
29    where
30        C: ConnectionTrait,
31    {
32        // so that self is dropped before entering await
33        exec_delete_only(self.query, db)
34    }
35
36    /// Execute an delete operation and return the deleted model
37    ///
38    /// # Panics
39    ///
40    /// Panics if the database backend does not support `DELETE RETURNING`
41    pub fn exec_with_returning<C>(
42        self,
43        db: &'a C,
44    ) -> impl Future<Output = Result<Option<<A::Entity as EntityTrait>::Model>, DbErr>> + 'a
45    where
46        C: ConnectionTrait,
47    {
48        exec_delete_with_returning_one::<A::Entity, _>(self.query, db)
49    }
50}
51
52impl<'a, E> DeleteMany<E>
53where
54    E: EntityTrait,
55{
56    /// Execute a DELETE operation on many ActiveModels
57    pub fn exec<C>(self, db: &'a C) -> impl Future<Output = Result<DeleteResult, DbErr>> + 'a
58    where
59        C: ConnectionTrait,
60    {
61        // so that self is dropped before entering await
62        exec_delete_only(self.query, db)
63    }
64
65    /// Execute an delete operation and return the deleted model
66    ///
67    /// # Panics
68    ///
69    /// Panics if the database backend does not support `DELETE RETURNING`
70    pub fn exec_with_returning<C>(
71        self,
72        db: &C,
73    ) -> impl Future<Output = Result<Vec<E::Model>, DbErr>> + '_
74    where
75        E: EntityTrait,
76        C: ConnectionTrait,
77    {
78        exec_delete_with_returning_many::<E, _>(self.query, db)
79    }
80}
81
82impl Deleter {
83    /// Instantiate a new [Deleter] by passing it a [DeleteStatement]
84    pub fn new(query: DeleteStatement) -> Self {
85        Self { query }
86    }
87
88    /// Execute a DELETE operation
89    pub fn exec<C>(self, db: &C) -> impl Future<Output = Result<DeleteResult, DbErr>> + '_
90    where
91        C: ConnectionTrait,
92    {
93        exec_delete(self.query, db)
94    }
95
96    /// Execute an delete operation and return the deleted model
97    ///
98    /// # Panics
99    ///
100    /// Panics if the database backend does not support `DELETE RETURNING`
101    pub fn exec_with_returning<E, C>(
102        self,
103        db: &C,
104    ) -> impl Future<Output = Result<Vec<E::Model>, DbErr>> + '_
105    where
106        E: EntityTrait,
107        C: ConnectionTrait,
108    {
109        exec_delete_with_returning_many::<E, _>(self.query, db)
110    }
111}
112
113async fn exec_delete_only<C>(query: DeleteStatement, db: &C) -> Result<DeleteResult, DbErr>
114where
115    C: ConnectionTrait,
116{
117    Deleter::new(query).exec(db).await
118}
119
120async fn exec_delete<C>(query: DeleteStatement, db: &C) -> Result<DeleteResult, DbErr>
121where
122    C: ConnectionTrait,
123{
124    let builder = db.get_database_backend();
125    let statement = builder.build(&query);
126
127    let result = db.execute(statement).await?;
128    Ok(DeleteResult {
129        rows_affected: result.rows_affected(),
130    })
131}
132
133async fn exec_delete_with_returning_one<E, C>(
134    mut query: DeleteStatement,
135    db: &C,
136) -> Result<Option<E::Model>, DbErr>
137where
138    E: EntityTrait,
139    C: ConnectionTrait,
140{
141    let models = match db.support_returning() {
142        true => {
143            let db_backend = db.get_database_backend();
144            let delete_statement = db_backend.build(&query.returning_all().to_owned());
145            SelectorRaw::<SelectModel<<E>::Model>>::from_statement(delete_statement)
146                .one(db)
147                .await?
148        }
149        false => unimplemented!("Database backend doesn't support RETURNING"),
150    };
151    Ok(models)
152}
153
154async fn exec_delete_with_returning_many<E, C>(
155    mut query: DeleteStatement,
156    db: &C,
157) -> Result<Vec<E::Model>, DbErr>
158where
159    E: EntityTrait,
160    C: ConnectionTrait,
161{
162    let models = match db.support_returning() {
163        true => {
164            let db_backend = db.get_database_backend();
165            let returning = Query::returning().exprs(
166                E::Column::iter().map(|c| c.select_enum_as(c.into_returning_expr(db_backend))),
167            );
168            let query = query.returning(returning);
169            let delete_statement = db_backend.build(&query.to_owned());
170            SelectorRaw::<SelectModel<<E>::Model>>::from_statement(delete_statement)
171                .all(db)
172                .await?
173        }
174        false => unimplemented!("Database backend doesn't support RETURNING"),
175    };
176    Ok(models)
177}