Do nothing on conflict (#1712)

* added Conflicted to TryInsertResult

clippy changes

fmt

change from basic if statement to matches

* changed to early return
This commit is contained in:
darkmmon 2023-06-21 22:47:17 +08:00 committed by GitHub
parent f7398d1c5c
commit 6e7950158a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 13 deletions

View File

@ -30,9 +30,9 @@ where
/// The types of results for an INSERT operation /// The types of results for an INSERT operation
#[derive(Debug)] #[derive(Debug)]
pub enum TryInsertResult<T> { pub enum TryInsertResult<T> {
/// The INSERT operation did not insert any value /// The INSERT statement did not have any value to insert
Empty, Empty,
/// Reserved /// The INSERT operation did not insert any valid value
Conflicted, Conflicted,
/// Successfully inserted /// Successfully inserted
Inserted(T), Inserted(T),
@ -50,10 +50,13 @@ where
A: 'a, A: 'a,
{ {
if self.insert_struct.columns.is_empty() { if self.insert_struct.columns.is_empty() {
TryInsertResult::Empty return TryInsertResult::Empty;
} else {
TryInsertResult::Inserted(self.insert_struct.exec(db).await)
} }
let temp = self.insert_struct.exec(db).await;
if matches!(temp, Err(DbErr::RecordNotInserted)) {
return TryInsertResult::Conflicted;
}
TryInsertResult::Inserted(temp)
} }
/// Execute an insert operation without returning (don't use `RETURNING` syntax) /// Execute an insert operation without returning (don't use `RETURNING` syntax)
@ -68,10 +71,13 @@ where
A: 'a, A: 'a,
{ {
if self.insert_struct.columns.is_empty() { if self.insert_struct.columns.is_empty() {
TryInsertResult::Empty return TryInsertResult::Empty;
} else {
TryInsertResult::Inserted(self.insert_struct.exec_without_returning(db).await)
} }
let temp = self.insert_struct.exec_without_returning(db).await;
if matches!(temp, Err(DbErr::RecordNotInserted)) {
return TryInsertResult::Conflicted;
}
TryInsertResult::Inserted(temp)
} }
/// Execute an insert operation and return the inserted model (use `RETURNING` syntax if database supported) /// Execute an insert operation and return the inserted model (use `RETURNING` syntax if database supported)
@ -85,10 +91,13 @@ where
A: 'a, A: 'a,
{ {
if self.insert_struct.columns.is_empty() { if self.insert_struct.columns.is_empty() {
TryInsertResult::Empty return TryInsertResult::Empty;
} else {
TryInsertResult::Inserted(self.insert_struct.exec_with_returning(db).await)
} }
let temp = self.insert_struct.exec_with_returning(db).await;
if matches!(temp, Err(DbErr::RecordNotInserted)) {
return TryInsertResult::Conflicted;
}
TryInsertResult::Inserted(temp)
} }
} }

View File

@ -211,6 +211,14 @@ where
/// Allow insert statement return safely if inserting nothing. /// Allow insert statement return safely if inserting nothing.
/// The database will not be affected. /// The database will not be affected.
pub fn do_nothing(self) -> TryInsert<A>
where
A: ActiveModelTrait,
{
TryInsert::from_insert(self)
}
/// alias to do_nothing
pub fn on_empty_do_nothing(self) -> TryInsert<A> pub fn on_empty_do_nothing(self) -> TryInsert<A>
where where
A: ActiveModelTrait, A: ActiveModelTrait,
@ -309,7 +317,7 @@ where
self self
} }
// helper function for on_empty_do_nothing in Insert<A> // helper function for do_nothing in Insert<A>
pub fn from_insert(insert: Insert<A>) -> Self { pub fn from_insert(insert: Insert<A>) -> Self {
Self { Self {
insert_struct: insert, insert_struct: insert,

View File

@ -3,6 +3,7 @@ pub mod common;
pub use common::{features::*, setup::*, TestContext}; pub use common::{features::*, setup::*, TestContext};
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use sea_orm::entity::prelude::*; use sea_orm::entity::prelude::*;
use sea_orm::TryInsertResult;
use sea_orm::{sea_query::OnConflict, Set}; use sea_orm::{sea_query::OnConflict, Set};
#[sea_orm_macros::test] #[sea_orm_macros::test]
@ -50,11 +51,24 @@ pub async fn create_insert_default(db: &DatabaseConnection) -> Result<(), DbErr>
ActiveModel { id: Set(3) }, ActiveModel { id: Set(3) },
ActiveModel { id: Set(4) }, ActiveModel { id: Set(4) },
]) ])
.on_conflict(on_conflict) .on_conflict(on_conflict.clone())
.exec(db) .exec(db)
.await; .await;
assert_eq!(res.err(), Some(DbErr::RecordNotInserted)); assert_eq!(res.err(), Some(DbErr::RecordNotInserted));
let res = Entity::insert_many([
ActiveModel { id: Set(1) },
ActiveModel { id: Set(2) },
ActiveModel { id: Set(3) },
ActiveModel { id: Set(4) },
])
.on_conflict(on_conflict)
.do_nothing()
.exec(db)
.await;
assert!(matches!(res, TryInsertResult::Conflicted));
Ok(()) Ok(())
} }