Update::many()
will not raise DbErr::RecordNotFound
error
This commit is contained in:
parent
602690e9a7
commit
91fb97c12a
@ -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()]
|
||||||
|
),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user