Add constraint method to DatabaseError trait

Override `constraint` method for `PgDatabaseError`.
This commit is contained in:
Florian Hübsch 2021-01-20 09:37:38 +01:00 committed by Ryan Leckey
parent d5e0f1b92b
commit 68cf2f9cdb
4 changed files with 55 additions and 0 deletions

View File

@ -158,6 +158,15 @@ pub trait DatabaseError: 'static + Send + Sync + StdError {
#[doc(hidden)]
fn into_error(self: Box<Self>) -> Box<dyn StdError + Send + Sync + 'static>;
/// Returns the name of the constraint that triggered the error, if applicable.
/// If the error was caused by a conflict of a unique index, this will be the index name.
///
/// ### Note
/// Currently only populated by the Postgres driver.
fn constraint(&self) -> Option<&str> {
None
}
}
impl dyn DatabaseError {

View File

@ -184,4 +184,8 @@ impl DatabaseError for PgDatabaseError {
fn into_error(self: Box<Self>) -> Box<dyn Error + Send + Sync + 'static> {
self
}
fn constraint(&self) -> Option<&str> {
self.constraint()
}
}

View File

@ -80,6 +80,42 @@ async fn it_can_inspect_errors() -> anyhow::Result<()> {
assert_eq!(err.code(), "42703");
assert_eq!(err.position(), Some(PgErrorPosition::Original(8)));
assert_eq!(err.routine(), Some("errorMissingColumn"));
assert_eq!(err.constraint(), None);
Ok(())
}
#[sqlx_macros::test]
async fn it_can_inspect_constraint_errors() -> anyhow::Result<()> {
let mut conn = new::<Postgres>().await?;
let res: Result<_, sqlx::Error> =
sqlx::query("INSERT INTO products VALUES (1, 'Product 1', 0);")
.execute(&mut conn)
.await;
let err = res.unwrap_err();
// can also do [as_database_error] or use `match ..`
let err = err.into_database_error().unwrap();
assert_eq!(
err.message(),
"new row for relation \"products\" violates check constraint \"products_price_check\""
);
assert_eq!(err.code().as_deref(), Some("23514"));
// can also do [downcast_ref]
let err: Box<PgDatabaseError> = err.downcast();
assert_eq!(err.severity(), PgSeverity::Error);
assert_eq!(
err.message(),
"new row for relation \"products\" violates check constraint \"products_price_check\""
);
assert_eq!(err.code(), "23514");
assert_eq!(err.position(), None);
assert_eq!(err.routine(), Some("ExecConstraints"));
assert_eq!(err.constraint(), Some("products_price_check"));
Ok(())
}

View File

@ -23,3 +23,9 @@ CREATE TYPE float_range AS RANGE
subtype = float8,
subtype_diff = float8mi
);
CREATE TABLE products (
product_no INTEGER,
name TEXT,
price NUMERIC CHECK (price > 0)
);