diff --git a/src/executor/insert.rs b/src/executor/insert.rs index be00dbed3..1af3c3384 100644 --- a/src/executor/insert.rs +++ b/src/executor/insert.rs @@ -30,9 +30,9 @@ where /// The types of results for an INSERT operation #[derive(Debug)] pub enum TryInsertResult { - /// 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) } } diff --git a/src/query/insert.rs b/src/query/insert.rs index 3fdb343c3..cf878dcd1 100644 --- a/src/query/insert.rs +++ b/src/query/insert.rs @@ -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 + where + A: ActiveModelTrait, + { + TryInsert::from_insert(self) + } + + /// alias to do_nothing pub fn on_empty_do_nothing(self) -> TryInsert where A: ActiveModelTrait, @@ -309,7 +317,7 @@ where self } - // helper function for on_empty_do_nothing in Insert + // helper function for do_nothing in Insert pub fn from_insert(insert: Insert) -> Self { Self { insert_struct: insert, diff --git a/tests/upsert_tests.rs b/tests/upsert_tests.rs index 748d5b0a3..05009b5b9 100644 --- a/tests/upsert_tests.rs +++ b/tests/upsert_tests.rs @@ -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(()) }