1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
910//! [PostgresClient](crate::PostgresClient)-related errors.
1112use std::fmt;
1314/// An error coming from Postgres.
15#[derive(Debug)]
16pub enum PostgresError {
17/// A determinate error from Postgres.
18Determinate(anyhow::Error),
19/// An indeterminate error from Postgres.
20Indeterminate(anyhow::Error),
21}
2223impl std::fmt::Display for PostgresError {
24fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25match self {
26 PostgresError::Determinate(x) => std::fmt::Display::fmt(x, f),
27 PostgresError::Indeterminate(x) => std::fmt::Display::fmt(x, f),
28 }
29 }
30}
3132impl std::error::Error for PostgresError {}
3334/// An impl of PartialEq purely for convenience in tests and debug assertions.
35#[cfg(any(test, debug_assertions))]
36impl PartialEq for PostgresError {
37fn eq(&self, other: &Self) -> bool {
38self.to_string() == other.to_string()
39 }
40}
4142impl From<anyhow::Error> for PostgresError {
43fn from(inner: anyhow::Error) -> Self {
44 PostgresError::Indeterminate(inner)
45 }
46}
4748impl From<std::io::Error> for PostgresError {
49fn from(x: std::io::Error) -> Self {
50 PostgresError::Indeterminate(anyhow::Error::new(x))
51 }
52}
5354impl From<deadpool_postgres::tokio_postgres::Error> for PostgresError {
55fn from(e: deadpool_postgres::tokio_postgres::Error) -> Self {
56let code = match e.as_db_error().map(|x| x.code()) {
57Some(x) => x,
58None => return PostgresError::Indeterminate(anyhow::Error::new(e)),
59 };
60match code {
61// Feel free to add more things to this allowlist as we encounter
62 // them as long as you're certain they're determinate.
63&deadpool_postgres::tokio_postgres::error::SqlState::T_R_SERIALIZATION_FAILURE => {
64 PostgresError::Determinate(anyhow::Error::new(e))
65 }
66_ => PostgresError::Indeterminate(anyhow::Error::new(e)),
67 }
68 }
69}
7071impl From<deadpool_postgres::PoolError> for PostgresError {
72fn from(x: deadpool_postgres::PoolError) -> Self {
73match x {
74// We have logic for turning a postgres Error into an ExternalError,
75 // so use it.
76deadpool_postgres::PoolError::Backend(x) => PostgresError::from(x),
77 x => PostgresError::Indeterminate(anyhow::Error::new(x)),
78 }
79 }
80}
8182impl From<tokio::task::JoinError> for PostgresError {
83fn from(x: tokio::task::JoinError) -> Self {
84 PostgresError::Indeterminate(anyhow::Error::new(x))
85 }
86}