Update::many() will not raise DbErr::RecordNotFound error

This commit is contained in:
Billy Chan 2021-10-04 11:18:42 +08:00
parent 602690e9a7
commit 91fb97c12a
No known key found for this signature in database
GPG Key ID: A2D690CAC7DF3CC7

View File

@ -7,9 +7,10 @@ use std::future::Future;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Updater { pub struct Updater {
query: UpdateStatement, query: UpdateStatement,
check_record_exists: bool,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq)]
pub struct UpdateResult { pub struct UpdateResult {
pub rows_affected: u64, pub rows_affected: u64,
} }
@ -39,7 +40,15 @@ where
impl Updater { impl Updater {
pub fn new(query: UpdateStatement) -> Self { pub fn new(query: UpdateStatement) -> Self {
Self { query } Self {
query,
check_record_exists: false,
}
}
pub fn check_record_exists(mut self) -> Self {
self.check_record_exists = true;
self
} }
pub fn exec( pub fn exec(
@ -47,7 +56,7 @@ impl Updater {
db: &DatabaseConnection, db: &DatabaseConnection,
) -> impl Future<Output = Result<UpdateResult, DbErr>> + '_ { ) -> impl Future<Output = Result<UpdateResult, DbErr>> + '_ {
let builder = db.get_database_backend(); let builder = db.get_database_backend();
exec_update(builder.build(&self.query), db) exec_update(builder.build(&self.query), db, self.check_record_exists)
} }
} }
@ -66,14 +75,18 @@ async fn exec_update_and_return_original<A>(
where where
A: ActiveModelTrait, A: ActiveModelTrait,
{ {
Updater::new(query).exec(db).await?; Updater::new(query).check_record_exists().exec(db).await?;
Ok(model) Ok(model)
} }
// Only Statement impl Send // Only Statement impl Send
async fn exec_update(statement: Statement, db: &DatabaseConnection) -> Result<UpdateResult, DbErr> { async fn exec_update(
statement: Statement,
db: &DatabaseConnection,
check_record_exists: bool,
) -> Result<UpdateResult, DbErr> {
let result = db.execute(statement).await?; let result = db.execute(statement).await?;
if result.rows_affected() == 0 { if check_record_exists && result.rows_affected() == 0 {
return Err(DbErr::RecordNotFound( return Err(DbErr::RecordNotFound(
"None of the database rows are affected".to_owned(), "None of the database rows are affected".to_owned(),
)); ));
@ -87,6 +100,7 @@ async fn exec_update(statement: Statement, db: &DatabaseConnection) -> Result<Up
mod tests { mod tests {
use crate::{entity::prelude::*, tests_cfg::*, *}; use crate::{entity::prelude::*, tests_cfg::*, *};
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use sea_query::Expr;
#[smol_potat::test] #[smol_potat::test]
async fn update_record_not_found_1() -> Result<(), DbErr> { async fn update_record_not_found_1() -> Result<(), DbErr> {
@ -104,6 +118,14 @@ mod tests {
last_insert_id: 0, last_insert_id: 0,
rows_affected: 0, rows_affected: 0,
}, },
MockExecResult {
last_insert_id: 0,
rows_affected: 0,
},
MockExecResult {
last_insert_id: 0,
rows_affected: 0,
},
]) ])
.into_connection(); .into_connection();
@ -145,6 +167,18 @@ mod tests {
assert_eq!( assert_eq!(
cake::Entity::update(cake::ActiveModel { cake::Entity::update(cake::ActiveModel {
name: Set("Cheese Cake".to_owned()),
..model.clone().into_active_model()
})
.exec(&db)
.await,
Err(DbErr::RecordNotFound(
"None of the database rows are affected".to_owned()
))
);
assert_eq!(
Update::one(cake::ActiveModel {
name: Set("Cheese Cake".to_owned()), name: Set("Cheese Cake".to_owned()),
..model.into_active_model() ..model.into_active_model()
}) })
@ -155,6 +189,15 @@ mod tests {
)) ))
); );
assert_eq!(
Update::many(cake::Entity)
.col_expr(cake::Column::Name, Expr::value("Cheese Cake".to_owned()))
.filter(cake::Column::Id.eq(2))
.exec(&db)
.await,
Ok(UpdateResult { rows_affected: 0 })
);
assert_eq!( assert_eq!(
db.into_transaction_log(), db.into_transaction_log(),
vec![ vec![
@ -173,6 +216,16 @@ mod tests {
r#"UPDATE "cake" SET "name" = $1 WHERE "cake"."id" = $2"#, r#"UPDATE "cake" SET "name" = $1 WHERE "cake"."id" = $2"#,
vec!["Cheese Cake".into(), 2i32.into()] vec!["Cheese Cake".into(), 2i32.into()]
), ),
Transaction::from_sql_and_values(
DbBackend::Postgres,
r#"UPDATE "cake" SET "name" = $1 WHERE "cake"."id" = $2"#,
vec!["Cheese Cake".into(), 2i32.into()]
),
Transaction::from_sql_and_values(
DbBackend::Postgres,
r#"UPDATE "cake" SET "name" = $1 WHERE "cake"."id" = $2"#,
vec!["Cheese Cake".into(), 2i32.into()]
),
] ]
); );