Added delete_by_id (#590)

* 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
This commit is contained in:
Shouvik Ghosh 2022-03-21 12:11:05 +05:30 committed by GitHub
parent 7a86ac0239
commit 12f66618f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 172 additions and 1 deletions

View File

@ -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() {

View File

@ -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,

View File

@ -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(())
}