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
|
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 {
|
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 {
|
fn is_noop(&self) -> bool {
|
||||||
self.query.get_values().is_empty()
|
self.query.get_values().is_empty()
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
pub mod common;
|
pub mod common;
|
||||||
|
|
||||||
pub use common::{bakery_chain::*, setup::*, TestContext};
|
pub use common::{bakery_chain::*, setup::*, TestContext};
|
||||||
use sea_orm::entity::prelude::*;
|
pub use sea_orm::{entity::prelude::*, *};
|
||||||
use sea_query::Query;
|
pub use sea_query::{Expr, Query};
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
#[sea_orm_macros::test]
|
#[sea_orm_macros::test]
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
@ -66,3 +67,121 @@ async fn main() -> Result<(), DbErr> {
|
|||||||
|
|
||||||
Ok(())
|
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