Skip to content

Commit

Permalink
Fix handling of deferred constraints for PostgreSQL (launchbadge#2913)
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomasdezeeuw authored and kukabi committed Feb 22, 2024
1 parent 7ec2201 commit 904b09b
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 5 deletions.
15 changes: 10 additions & 5 deletions sqlx-postgres/src/connection/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,13 +402,18 @@ impl<'c> Executor<'c> for &'c mut PgConnection {
let s = self.run(sql, arguments, 1, persistent, metadata).await?;
pin_mut!(s);

while let Some(s) = s.try_next().await? {
if let Either::Right(r) = s {
return Ok(Some(r));
// With deferred constraints we need to check all responses as we
// could get a OK response (with uncommitted data), only to get an
// error response after (when the deferred constraint is actually
// checked).
let mut ret = None;
while let Some(result) = s.try_next().await? {
match result {
Either::Right(r) if ret.is_none() => ret = Some(r),
_ => {}
}
}

Ok(None)
Ok(ret)
})
}

Expand Down
24 changes: 24 additions & 0 deletions tests/postgres/postgres.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1813,3 +1813,27 @@ async fn test_shrink_buffers() -> anyhow::Result<()> {

Ok(())
}

#[sqlx_macros::test]
async fn test_error_handling_with_deferred_constraints() -> anyhow::Result<()> {
let mut conn = new::<Postgres>().await?;

sqlx::query("CREATE TABLE IF NOT EXISTS deferred_constraint ( id INTEGER PRIMARY KEY )")
.execute(&mut conn)
.await?;

sqlx::query("CREATE TABLE IF NOT EXISTS deferred_constraint_fk ( fk INTEGER CONSTRAINT deferred_fk REFERENCES deferred_constraint(id) DEFERRABLE INITIALLY DEFERRED )")
.execute(&mut conn)
.await?;

let result: sqlx::Result<i32> =
sqlx::query_scalar("INSERT INTO deferred_constraint_fk VALUES (1) RETURNING fk")
.fetch_one(&mut conn)
.await;

let err = result.unwrap_err();
let db_err = err.as_database_error().unwrap();
assert_eq!(db_err.constraint(), Some("deferred_fk"));

Ok(())
}

0 comments on commit 904b09b

Please sign in to comment.