From 5069f920015eded16993ee4c75557a9befde073f Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Fri, 11 Jun 2021 23:04:41 +0800 Subject: [PATCH] Delete and example --- examples/sqlx-mysql/Readme.md | 4 ++ examples/sqlx-mysql/src/operation.rs | 5 ++ sea-orm-macros/src/derives/active_model.rs | 6 +- src/connector/delete.rs | 71 ++++++++++++++++++++++ src/connector/mod.rs | 2 + src/entity/active_model.rs | 11 +++- src/entity/base.rs | 27 +++++++- 7 files changed, 121 insertions(+), 5 deletions(-) create mode 100644 src/connector/delete.rs diff --git a/examples/sqlx-mysql/Readme.md b/examples/sqlx-mysql/Readme.md index 2f479722..f7e5d7bc 100644 --- a/examples/sqlx-mysql/Readme.md +++ b/examples/sqlx-mysql/Readme.md @@ -120,6 +120,10 @@ UPDATE `fruit` SET `name` = 'banana banana' WHERE `fruit`.`id` = 22 Updated: ActiveModel { id: ActiveValue { value: 22, state: Unchanged }, name: ActiveValue { value: "banana banana", state: Set }, cake_id: ActiveValue { value: None, state: Unchanged } } +DELETE FROM `fruit` WHERE `fruit`.`id` = 22 + +Deleted: DeleteResult { rows_affected: 1 } + ===== ===== INSERT INTO `fruit` (`name`) VALUES ('pineapple') diff --git a/examples/sqlx-mysql/src/operation.rs b/examples/sqlx-mysql/src/operation.rs index 19e87a9a..fe21d7be 100644 --- a/examples/sqlx-mysql/src/operation.rs +++ b/examples/sqlx-mysql/src/operation.rs @@ -61,6 +61,11 @@ pub async fn save_active_model(db: &Database) -> Result<(), ExecErr> { println!(); println!("Updated: {:?}\n", banana); + let result = banana.delete(db).await?; + + println!(); + println!("Deleted: {:?}\n", result); + Ok(()) } diff --git a/sea-orm-macros/src/derives/active_model.rs b/sea-orm-macros/src/derives/active_model.rs index 8fc18874..6ba9c68f 100644 --- a/sea-orm-macros/src/derives/active_model.rs +++ b/sea-orm-macros/src/derives/active_model.rs @@ -40,6 +40,10 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result Result { sea_orm::save_active_model::(self, db).await } + + pub async fn delete(self, db: &sea_orm::Database) -> Result { + sea_orm::delete_active_model::(self, db).await + } } impl Default for ActiveModel { @@ -56,7 +60,7 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result for Model { + impl sea_orm::IntoActiveModel for ::Model { fn into_active_model(self) -> ActiveModel { self.into() } diff --git a/src/connector/delete.rs b/src/connector/delete.rs new file mode 100644 index 00000000..2a6e8903 --- /dev/null +++ b/src/connector/delete.rs @@ -0,0 +1,71 @@ +use crate::{ + ActiveModelTrait, Connection, Database, DeleteMany, DeleteOne, EntityTrait, ExecErr, Statement, +}; +use sea_query::{DeleteStatement, QueryBuilder}; +use std::future::Future; + +#[derive(Clone, Debug)] +pub struct Deleter { + query: DeleteStatement, +} + +#[derive(Clone, Debug)] +pub struct DeleteResult { + pub rows_affected: u64, +} + +impl<'a, A: 'a> DeleteOne +where + A: ActiveModelTrait, +{ + pub fn exec( + self, + db: &'a Database, + ) -> impl Future> + 'a { + // so that self is dropped before entering await + exec_delete_only(self.query, db) + } +} + +impl<'a, E> DeleteMany +where + E: EntityTrait, +{ + pub fn exec( + self, + db: &'a Database, + ) -> impl Future> + 'a { + // so that self is dropped before entering await + exec_delete_only(self.query, db) + } +} + +impl Deleter { + pub fn new(query: DeleteStatement) -> Self { + Self { query } + } + + pub fn build(&self, builder: B) -> Statement + where + B: QueryBuilder, + { + self.query.build(builder).into() + } + + pub fn exec(self, db: &Database) -> impl Future> + '_ { + let builder = db.get_query_builder_backend(); + exec_delete(self.build(builder), db) + } +} + +async fn exec_delete_only(query: DeleteStatement, db: &Database) -> Result { + Deleter::new(query).exec(db).await +} + +// Only Statement impl Send +async fn exec_delete(statement: Statement, db: &Database) -> Result { + let result = db.get_connection().execute(statement).await?; + Ok(DeleteResult { + rows_affected: result.rows_affected(), + }) +} diff --git a/src/connector/mod.rs b/src/connector/mod.rs index 8ae914c2..68591ad6 100644 --- a/src/connector/mod.rs +++ b/src/connector/mod.rs @@ -1,9 +1,11 @@ +mod delete; mod executor; mod insert; mod paginator; mod select; mod update; +pub use delete::*; pub use executor::*; pub use insert::*; pub use paginator::*; diff --git a/src/entity/active_model.rs b/src/entity/active_model.rs index 5d9aa7b2..017ed28c 100644 --- a/src/entity/active_model.rs +++ b/src/entity/active_model.rs @@ -1,4 +1,4 @@ -use crate::{Database, EntityTrait, ExecErr, Iterable, PrimaryKeyToColumn, Value}; +use crate::{Database, DeleteResult, EntityTrait, ExecErr, Iterable, PrimaryKeyToColumn, Value}; use std::fmt::Debug; #[derive(Clone, Debug, Default)] @@ -268,3 +268,12 @@ where let exec = E::update(am).exec(db); exec.await } + +pub async fn delete_active_model(am: A, db: &Database) -> Result +where + A: ActiveModelTrait, + E: EntityTrait, +{ + let exec = E::delete(am).exec(db); + exec.await +} diff --git a/src/entity/base.rs b/src/entity/base.rs index 497e22f2..be4811b6 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, UpdateOne, + ActiveModelTrait, ColumnTrait, Delete, DeleteOne, FromQueryResult, Insert, ModelTrait, + OneOrManyActiveModel, PrimaryKeyToColumn, PrimaryKeyTrait, QueryFilter, RelationBuilder, + RelationTrait, RelationType, Select, Update, UpdateOne, }; use sea_query::{Iden, IntoValueTuple}; use std::fmt::Debug; @@ -217,4 +217,25 @@ pub trait EntityTrait: EntityName { { Update::one(model) } + + /// ``` + /// use sea_orm::{entity::*, query::*, tests_cfg::fruit, sea_query::PostgresQueryBuilder}; + /// + /// let orange = fruit::ActiveModel { + /// id: Set(3), + /// ..Default::default() + /// }; + /// assert_eq!( + /// fruit::Entity::delete(orange) + /// .build(PostgresQueryBuilder) + /// .to_string(), + /// r#"DELETE FROM "fruit" WHERE "fruit"."id" = 3"#, + /// ); + /// ``` + fn delete(model: A) -> DeleteOne + where + A: ActiveModelTrait, + { + Delete::one(model) + } }