Update many with returning
This commit is contained in:
parent
19e761e73d
commit
53caf94af9
@ -45,6 +45,16 @@ where
|
||||
{
|
||||
Updater::new(self.query).exec(db).await
|
||||
}
|
||||
|
||||
/// Execute an update operation and return the updated model (use `RETURNING` syntax if database supported)
|
||||
pub async fn exec_with_returning<C>(self, db: &'a C) -> Result<Vec<E::Model>, DbErr>
|
||||
where
|
||||
C: ConnectionTrait,
|
||||
{
|
||||
Updater::new(self.query)
|
||||
.exec_update_with_returning::<E, _>(db)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
impl Updater {
|
||||
@ -123,6 +133,36 @@ impl Updater {
|
||||
}
|
||||
}
|
||||
|
||||
async fn exec_update_with_returning<E, C>(mut self, db: &C) -> Result<Vec<E::Model>, DbErr>
|
||||
where
|
||||
E: EntityTrait,
|
||||
C: ConnectionTrait,
|
||||
{
|
||||
if self.is_noop() {
|
||||
return Ok(vec![]);
|
||||
}
|
||||
|
||||
match db.support_returning() {
|
||||
true => {
|
||||
let returning =
|
||||
Query::returning().exprs(E::Column::iter().map(|c| c.select_as(Expr::col(c))));
|
||||
self.query.returning(returning);
|
||||
let db_backend = db.get_database_backend();
|
||||
let models: Vec<E::Model> = SelectorRaw::<SelectModel<E::Model>>::from_statement(
|
||||
db_backend.build(&self.query),
|
||||
)
|
||||
.all(db)
|
||||
.await?;
|
||||
// If we got an empty Vec then we are updating a row that does not exist.
|
||||
match models.is_empty() {
|
||||
true => Err(DbErr::RecordNotUpdated),
|
||||
false => Ok(models),
|
||||
}
|
||||
}
|
||||
false => unimplemented!("Database backend doesn't support RETURNING"),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_noop(&self) -> bool {
|
||||
self.query.get_values().is_empty()
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
pub mod common;
|
||||
|
||||
pub use common::{bakery_chain::*, setup::*, TestContext};
|
||||
use sea_orm::entity::prelude::*;
|
||||
use sea_query::Query;
|
||||
pub use sea_orm::{entity::prelude::*, *};
|
||||
pub use sea_query::{Expr, Query};
|
||||
use serde_json::json;
|
||||
|
||||
#[sea_orm_macros::test]
|
||||
#[cfg(any(
|
||||
@ -66,3 +67,121 @@ async fn main() -> Result<(), DbErr> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[sea_orm_macros::test]
|
||||
#[cfg(any(
|
||||
feature = "sqlx-mysql",
|
||||
feature = "sqlx-sqlite",
|
||||
feature = "sqlx-postgres"
|
||||
))]
|
||||
#[cfg_attr(
|
||||
any(feature = "sqlx-mysql", feature = "sqlx-sqlite"),
|
||||
should_panic(expected = "Database backend doesn't support RETURNING")
|
||||
)]
|
||||
async fn update_many() {
|
||||
pub use common::{features::*, setup::*, TestContext};
|
||||
use edit_log::*;
|
||||
|
||||
let run = || async {
|
||||
let ctx = TestContext::new("returning_tests_update_many").await;
|
||||
let db = &ctx.db;
|
||||
|
||||
create_tables(db).await?;
|
||||
|
||||
Entity::insert(
|
||||
Model {
|
||||
id: 1,
|
||||
action: "before_save".into(),
|
||||
values: json!({ "id": "unique-id-001" }),
|
||||
}
|
||||
.into_active_model(),
|
||||
)
|
||||
.exec(db)
|
||||
.await?;
|
||||
|
||||
Entity::insert(
|
||||
Model {
|
||||
id: 2,
|
||||
action: "before_save".into(),
|
||||
values: json!({ "id": "unique-id-002" }),
|
||||
}
|
||||
.into_active_model(),
|
||||
)
|
||||
.exec(db)
|
||||
.await?;
|
||||
|
||||
Entity::insert(
|
||||
Model {
|
||||
id: 3,
|
||||
action: "before_save".into(),
|
||||
values: json!({ "id": "unique-id-003" }),
|
||||
}
|
||||
.into_active_model(),
|
||||
)
|
||||
.exec(db)
|
||||
.await?;
|
||||
|
||||
assert_eq!(
|
||||
Entity::find().all(db).await?,
|
||||
[
|
||||
Model {
|
||||
id: 1,
|
||||
action: "before_save".into(),
|
||||
values: json!({ "id": "unique-id-001" }),
|
||||
},
|
||||
Model {
|
||||
id: 2,
|
||||
action: "before_save".into(),
|
||||
values: json!({ "id": "unique-id-002" }),
|
||||
},
|
||||
Model {
|
||||
id: 3,
|
||||
action: "before_save".into(),
|
||||
values: json!({ "id": "unique-id-003" }),
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
// Update many with returning
|
||||
assert_eq!(
|
||||
Entity::update_many()
|
||||
.col_expr(
|
||||
Column::Values,
|
||||
Expr::value(json!({ "remarks": "save log" }))
|
||||
)
|
||||
.filter(Column::Action.eq("before_save"))
|
||||
.exec_with_returning(db)
|
||||
.await?,
|
||||
[
|
||||
Model {
|
||||
id: 1,
|
||||
action: "before_save".into(),
|
||||
values: json!({ "remarks": "save log" }),
|
||||
},
|
||||
Model {
|
||||
id: 2,
|
||||
action: "before_save".into(),
|
||||
values: json!({ "remarks": "save log" }),
|
||||
},
|
||||
Model {
|
||||
id: 3,
|
||||
action: "before_save".into(),
|
||||
values: json!({ "remarks": "save log" }),
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
// No-op
|
||||
assert_eq!(
|
||||
Entity::update_many()
|
||||
.filter(Column::Action.eq("before_save"))
|
||||
.exec_with_returning(db)
|
||||
.await?,
|
||||
[]
|
||||
);
|
||||
|
||||
Result::<(), DbErr>::Ok(())
|
||||
};
|
||||
|
||||
run().await.unwrap();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user