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:
parent
7a86ac0239
commit
12f66618f9
@ -745,10 +745,124 @@ pub trait EntityTrait: EntityName {
|
|||||||
fn delete_many() -> DeleteMany<Self> {
|
fn delete_many() -> DeleteMany<Self> {
|
||||||
Delete::many(Self::default())
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
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]
|
#[test]
|
||||||
#[cfg(feature = "macros")]
|
#[cfg(feature = "macros")]
|
||||||
fn entity_model_1() {
|
fn entity_model_1() {
|
||||||
|
@ -11,7 +11,7 @@ pub struct Deleter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The result of a DELETE operation
|
/// The result of a DELETE operation
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct DeleteResult {
|
pub struct DeleteResult {
|
||||||
/// The number of rows affected by the DELETE operation
|
/// The number of rows affected by the DELETE operation
|
||||||
pub rows_affected: u64,
|
pub rows_affected: u64,
|
||||||
|
57
tests/delete_by_id_tests.rs
Normal file
57
tests/delete_by_id_tests.rs
Normal 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(())
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user