Skip to content

Commit

Permalink
Added delete_by_id (#590)
Browse files Browse the repository at this point in the history
* Added delete_by_id

* Added an integration test

* Added composite key example

* Remove extra find_by_id in delete_by_id test

* Added unit test with composite primary key
  • Loading branch information
ShouvikGhosh2048 authored Mar 21, 2022
1 parent 7a86ac0 commit 12f6661
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 1 deletion.
114 changes: 114 additions & 0 deletions src/entity/base_entity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -745,10 +745,124 @@ pub trait EntityTrait: EntityName {
fn delete_many() -> DeleteMany<Self> {
Delete::many(Self::default())
}

/// Delete a model based on primary key
///
/// # Example
///
/// ```
/// # use sea_orm::{error::*, tests_cfg::*, *};
/// #
/// # #[smol_potat::main]
/// # #[cfg(feature = "mock")]
/// # pub async fn main() -> Result<(), DbErr> {
/// #
/// # let db = MockDatabase::new(DbBackend::Postgres)
/// # .append_exec_results(vec![
/// # MockExecResult {
/// # last_insert_id: 0,
/// # rows_affected: 1,
/// # },
/// # ])
/// # .into_connection();
/// #
/// use sea_orm::{entity::*, query::*, tests_cfg::fruit};
///
/// let delete_result = fruit::Entity::delete_by_id(1).exec(&db).await?;
///
/// assert_eq!(delete_result.rows_affected, 1);
///
/// assert_eq!(
/// db.into_transaction_log(),
/// vec![Transaction::from_sql_and_values(
/// DbBackend::Postgres,
/// r#"DELETE FROM "fruit" WHERE "fruit"."id" = $1"#,
/// vec![1i32.into()]
/// )]
/// );
/// #
/// # Ok(())
/// # }
/// ```
/// Delete by composite key
/// ```
/// # use sea_orm::{error::*, tests_cfg::*, *};
/// #
/// # #[smol_potat::main]
/// # #[cfg(feature = "mock")]
/// # pub async fn main() -> Result<(), DbErr> {
///
/// # let db = MockDatabase::new(DbBackend::Postgres)
/// # .append_exec_results(vec![
/// # MockExecResult {
/// # last_insert_id: 0,
/// # rows_affected: 1,
/// # },
/// # ])
/// # .into_connection();
/// #
/// use sea_orm::{entity::*, query::*, tests_cfg::cake_filling};
///
/// let delete_result = cake_filling::Entity::delete_by_id((2, 3)).exec(&db).await?;
///
/// assert_eq!(delete_result.rows_affected, 1);
///
/// assert_eq!(
/// db.into_transaction_log(),
/// vec![Transaction::from_sql_and_values(
/// DbBackend::Postgres,
/// r#"DELETE FROM "cake_filling" WHERE "cake_filling"."cake_id" = $1 AND "cake_filling"."filling_id" = $2"#,
/// vec![2i32.into(), 3i32.into()]
/// )]
/// );
/// #
/// # Ok(())
/// # }
/// ```
fn delete_by_id(values: <Self::PrimaryKey as PrimaryKeyTrait>::ValueType) -> DeleteMany<Self> {
let mut delete = Self::delete_many();
let mut keys = Self::PrimaryKey::iter();
for v in values.into_value_tuple() {
if let Some(key) = keys.next() {
let col = key.into_column();
delete = delete.filter(col.eq(v));
} else {
panic!("primary key arity mismatch");
}
}
if keys.next().is_some() {
panic!("primary key arity mismatch");
}
delete
}
}

#[cfg(test)]
mod tests {
#[test]
fn test_delete_by_id_1() {
use crate::tests_cfg::cake;
use crate::{entity::*, query::*, DbBackend};
assert_eq!(
cake::Entity::delete_by_id(1)
.build(DbBackend::Sqlite)
.to_string(),
r#"DELETE FROM "cake" WHERE "cake"."id" = 1"#,
);
}

#[test]
fn test_delete_by_id_2() {
use crate::tests_cfg::cake_filling_price;
use crate::{entity::*, query::*, DbBackend};
assert_eq!(
cake_filling_price::Entity::delete_by_id((1, 2))
.build(DbBackend::Sqlite)
.to_string(),
r#"DELETE FROM "public"."cake_filling_price" WHERE "cake_filling_price"."cake_id" = 1 AND "cake_filling_price"."filling_id" = 2"#,
);
}

#[test]
#[cfg(feature = "macros")]
fn entity_model_1() {
Expand Down
2 changes: 1 addition & 1 deletion src/executor/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub struct Deleter {
}

/// The result of a DELETE operation
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq)]
pub struct DeleteResult {
/// The number of rows affected by the DELETE operation
pub rows_affected: u64,
Expand Down
57 changes: 57 additions & 0 deletions tests/delete_by_id_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
pub mod common;
pub use common::{features::*, setup::*, TestContext};
use sea_orm::{entity::prelude::*, DatabaseConnection, IntoActiveModel};

#[sea_orm_macros::test]
#[cfg(any(
feature = "sqlx-mysql",
feature = "sqlx-sqlite",
feature = "sqlx-postgres"
))]
async fn main() -> Result<(), DbErr> {
let ctx = TestContext::new("delete_by_id_tests").await;
create_tables(&ctx.db).await?;
create_and_delete_applog(&ctx.db).await?;

ctx.delete().await;

Ok(())
}

pub async fn create_and_delete_applog(db: &DatabaseConnection) -> Result<(), DbErr> {
let log1 = applog::Model {
id: 1,
action: "Testing".to_owned(),
json: Json::String("HI".to_owned()),
created_at: "2021-09-17T17:50:20+08:00".parse().unwrap(),
};

Applog::insert(log1.clone().into_active_model())
.exec(db)
.await?;

let log2 = applog::Model {
id: 2,
action: "Tests".to_owned(),
json: Json::String("HELLO".to_owned()),
created_at: "2022-09-17T17:50:20+08:00".parse().unwrap(),
};

Applog::insert(log2.clone().into_active_model())
.exec(db)
.await?;

let delete_res = Applog::delete_by_id(2).exec(db).await?;
assert_eq!(delete_res.rows_affected, 1);

let find_res = Applog::find_by_id(1).all(db).await?;
assert_eq!(find_res, vec![log1]);

let find_res = Applog::find_by_id(2).all(db).await?;
assert_eq!(find_res, vec![]);

let delete_res = Applog::delete_by_id(3).exec(db).await?;
assert_eq!(delete_res.rows_affected, 0);

Ok(())
}

0 comments on commit 12f6661

Please sign in to comment.