Skip to main content

sea_orm_spanner/
error.rs

1use {
2    gcloud_gax::{grpc::Status, retry::TryAs},
3    gcloud_spanner::session::SessionError,
4    sea_orm::DbErr,
5    thiserror::Error,
6};
7
8/// Error type for use in Spanner transactions that satisfies google-cloud-spanner bounds
9#[derive(Debug)]
10pub enum SpannerTxError {
11    Grpc(Status),
12    Session(SessionError),
13    Db(DbErr),
14}
15
16impl From<Status> for SpannerTxError {
17    fn from(err: Status) -> Self {
18        SpannerTxError::Grpc(err)
19    }
20}
21
22impl From<SessionError> for SpannerTxError {
23    fn from(err: SessionError) -> Self {
24        SpannerTxError::Session(err)
25    }
26}
27
28impl From<DbErr> for SpannerTxError {
29    fn from(err: DbErr) -> Self {
30        SpannerTxError::Db(err)
31    }
32}
33
34impl TryAs<Status> for SpannerTxError {
35    fn try_as(&self) -> Option<&Status> {
36        match self {
37            SpannerTxError::Grpc(s) => Some(s),
38            _ => None,
39        }
40    }
41}
42
43impl std::fmt::Display for SpannerTxError {
44    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45        match self {
46            SpannerTxError::Grpc(e) => write!(f, "gRPC error: {}", e),
47            SpannerTxError::Session(e) => write!(f, "Session error: {}", e),
48            SpannerTxError::Db(e) => write!(f, "Database error: {}", e),
49        }
50    }
51}
52
53impl std::error::Error for SpannerTxError {}
54
55#[derive(Error, Debug)]
56pub enum SpannerDbErr {
57    #[error("Spanner connection error: {0}")]
58    Connection(String),
59
60    #[error("Spanner query error: {0}")]
61    Query(String),
62
63    #[error("Spanner execution error: {0}")]
64    Execution(String),
65
66    #[error("Transaction error: {0}")]
67    Transaction(String),
68
69    #[error("Row parse error: {0}")]
70    RowParse(String),
71
72    #[error("Type conversion error: column={column}, expected={expected}, got={got}")]
73    TypeConversion {
74        column: String,
75        expected: String,
76        got: String,
77    },
78
79    #[error("Column not found: {0}")]
80    ColumnNotFound(String),
81
82    #[error("Invalid configuration: {0}")]
83    InvalidConfig(String),
84}
85
86impl From<SpannerDbErr> for DbErr {
87    fn from(err: SpannerDbErr) -> Self {
88        match err {
89            SpannerDbErr::Connection(msg) => DbErr::Conn(sea_orm::RuntimeErr::Internal(msg)),
90            SpannerDbErr::Query(msg) => DbErr::Query(sea_orm::RuntimeErr::Internal(msg)),
91            SpannerDbErr::Execution(msg) => DbErr::Exec(sea_orm::RuntimeErr::Internal(msg)),
92            SpannerDbErr::Transaction(msg) => DbErr::Query(sea_orm::RuntimeErr::Internal(msg)),
93            SpannerDbErr::RowParse(msg) => DbErr::Type(msg),
94            SpannerDbErr::TypeConversion {
95                column,
96                expected,
97                got,
98            } => DbErr::Type(format!(
99                "column={}, expected={}, got={}",
100                column, expected, got
101            )),
102            SpannerDbErr::ColumnNotFound(col) => DbErr::Type(format!("column not found: {}", col)),
103            SpannerDbErr::InvalidConfig(msg) => DbErr::Conn(sea_orm::RuntimeErr::Internal(msg)),
104        }
105    }
106}
107
108impl From<gcloud_spanner::client::Error> for SpannerDbErr {
109    fn from(err: gcloud_spanner::client::Error) -> Self {
110        SpannerDbErr::Connection(err.to_string())
111    }
112}
113
114impl From<gcloud_spanner::row::Error> for SpannerDbErr {
115    fn from(err: gcloud_spanner::row::Error) -> Self {
116        SpannerDbErr::RowParse(err.to_string())
117    }
118}