ts_sql/
error.rs

1//! Trait for mapping certain postgres errors.
2
3use postgres::error::SqlState;
4
5/// Trait for mapping certain postgres errors.
6pub trait SqlError: Sized {
7    /// Map a foreign key violation to a different error type.
8    fn fk_violation<E, F: FnOnce() -> E>(self, f: F) -> Result<Self, E>;
9
10    /// Returns if the SQL error is a foreign key violation.
11    fn is_fk_violation(&self) -> bool;
12
13    /// Returns if the SQL error is a unique violation.
14    fn is_unique_violation(&self) -> bool;
15
16    /// Map a unique violation to a different error type.
17    fn unique_violation<E, F: FnOnce() -> E>(self, f: F) -> Result<Self, E>;
18}
19
20impl<T> SqlError for Result<T, postgres::Error> {
21    fn fk_violation<E, F: FnOnce() -> E>(self, f: F) -> Result<Self, E> {
22        if let Err(error) = &self
23            && let Some(code) = error.code()
24            && *code == SqlState::FOREIGN_KEY_VIOLATION
25        {
26            Err(f())
27        } else {
28            Ok(self)
29        }
30    }
31
32    fn unique_violation<E, F: FnOnce() -> E>(self, f: F) -> Result<Self, E> {
33        if let Err(error) = &self
34            && let Some(code) = error.code()
35            && *code == SqlState::UNIQUE_VIOLATION
36        {
37            Err(f())
38        } else {
39            Ok(self)
40        }
41    }
42
43    fn is_fk_violation(&self) -> bool {
44        if let Err(error) = &self
45            && let Some(code) = error.code()
46            && *code == SqlState::FOREIGN_KEY_VIOLATION
47        {
48            true
49        } else {
50            false
51        }
52    }
53
54    fn is_unique_violation(&self) -> bool {
55        if let Err(error) = &self
56            && let Some(code) = error.code()
57            && *code == SqlState::UNIQUE_VIOLATION
58        {
59            true
60        } else {
61            false
62        }
63    }
64}