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
#[derive(Debug)]
pub enum TryInsertResult<T> {
/// The INSERT operation did not insert any value
/// The INSERT statement did not have any value to insert
Empty,
/// Reserved
/// The INSERT operation did not insert any valid value
Conflicted,
/// Successfully inserted
Inserted(T),
@ -50,10 +50,13 @@ where
A: 'a,
{
if self.insert_struct.columns.is_empty() {
TryInsertResult::Empty
} else {
TryInsertResult::Inserted(self.insert_struct.exec(db).await)
return TryInsertResult::Empty;
}
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)
@ -68,10 +71,13 @@ where
A: 'a,
{
if self.insert_struct.columns.is_empty() {
TryInsertResult::Empty
} else {
TryInsertResult::Inserted(self.insert_struct.exec_without_returning(db).await)
return TryInsertResult::Empty;
}
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)
@ -85,10 +91,13 @@ where
A: 'a,
{
if self.insert_struct.columns.is_empty() {
TryInsertResult::Empty
} else {
TryInsertResult::Inserted(self.insert_struct.exec_with_returning(db).await)
return TryInsertResult::Empty;
}
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.
/// 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>
where
A: ActiveModelTrait,
@ -309,7 +317,7 @@ where
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 {
Self {
insert_struct: insert,

View File

@ -3,6 +3,7 @@ pub mod common;
pub use common::{features::*, setup::*, TestContext};
use pretty_assertions::assert_eq;
use sea_orm::entity::prelude::*;
use sea_orm::TryInsertResult;
use sea_orm::{sea_query::OnConflict, Set};
#[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(4) },
])
.on_conflict(on_conflict)
.on_conflict(on_conflict.clone())
.exec(db)
.await;
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(())
}