Skip to content

Commit

Permalink
PostgreSQL insert many with returning
Browse files Browse the repository at this point in the history
  • Loading branch information
billy1624 committed Sep 8, 2022
1 parent d532deb commit 6d3ba03
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ pub enum DbErr {
Json(String),
/// A migration error
Migration(String),
/// None of the records are being inserted into the database,
/// if you insert with upcert expression that means
/// all of them conflict with existing records in the database
RecordNotInserted(String),
}

impl std::error::Error for DbErr {}
Expand All @@ -32,6 +36,7 @@ impl std::fmt::Display for DbErr {
Self::Type(s) => write!(f, "Type Error: {}", s),
Self::Json(s) => write!(f, "Json Error: {}", s),
Self::Migration(s) => write!(f, "Migration Error: {}", s),
Self::RecordNotInserted(s) => write!(f, "RecordNotInserted Error: {}", s),
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/executor/insert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,10 @@ where
let cols = PrimaryKey::<A>::iter()
.map(|col| col.to_string())
.collect::<Vec<_>>();
let res = db.query_one(statement).await?.unwrap();
let rows = db.query_all(statement).await?;
let res = rows.last().ok_or_else(|| {
DbErr::RecordNotInserted("None of the records are being inserted".to_owned())
})?;
res.try_get_many("", cols.as_ref()).ok()
}
false => {
Expand Down
65 changes: 65 additions & 0 deletions tests/upsert_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
pub mod common;

pub use common::{features::*, setup::*, TestContext};
use pretty_assertions::assert_eq;
use sea_orm::entity::prelude::*;
use sea_orm::{sea_query::OnConflict, Set};

#[sea_orm_macros::test]
#[cfg(feature = "sqlx-postgres")]
async fn main() -> Result<(), DbErr> {
let ctx = TestContext::new("upsert_tests").await;
create_tables(&ctx.db).await?;
create_insert_default(&ctx.db).await?;
ctx.delete().await;

Ok(())
}

pub async fn create_insert_default(db: &DatabaseConnection) -> Result<(), DbErr> {
use insert_default::*;

let on_conflict = OnConflict::column(Column::Id).do_nothing().to_owned();

let res = Entity::insert_many([
ActiveModel { id: Set(1) },
ActiveModel { id: Set(2) },
ActiveModel { id: Set(3) },
])
.on_conflict(on_conflict.clone())
.exec(db)
.await;

assert_eq!(res?.last_insert_id, 3);

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.clone())
.exec(db)
.await;

assert_eq!(res?.last_insert_id, 4);

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)
.exec(db)
.await;

assert_eq!(
res.err(),
Some(DbErr::RecordNotInserted(
"None of the records are being inserted".to_owned()
))
);

Ok(())
}

0 comments on commit 6d3ba03

Please sign in to comment.