Skip to main content

databend_driver_core/
error.rs

1// Copyright 2021 Datafuse Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use geozero::error::GeozeroError;
16
17#[derive(Debug)]
18pub struct ConvertError {
19    target: &'static str,
20    data: String,
21    message: Option<String>,
22}
23
24impl ConvertError {
25    pub fn new(target: &'static str, data: String) -> Self {
26        ConvertError {
27            target,
28            data,
29            message: None,
30        }
31    }
32
33    pub fn with_message(mut self, message: String) -> Self {
34        self.message = Some(message);
35        self
36    }
37}
38
39#[derive(Debug)]
40pub enum Error {
41    Parsing(String),
42    Protocol(String),
43    Transport(String),
44    IO(String),
45    BadArgument(String),
46    InvalidResponse(String),
47    Api(databend_client::Error),
48    Arrow(arrow_schema::ArrowError),
49    Convert(ConvertError),
50}
51
52impl Error {
53    fn formatted_message(&self) -> String {
54        match self {
55            Error::Parsing(msg) => format!("ParseError: {msg}"),
56            Error::Protocol(msg) => format!("ProtocolError: {msg}"),
57            Error::Transport(msg) => format!("TransportError: {msg}"),
58            Error::IO(msg) => format!("IOError: {msg}"),
59            Error::BadArgument(msg) => format!("BadArgument: {msg}"),
60            Error::InvalidResponse(msg) => format!("ResponseError: {msg}"),
61            Error::Arrow(e) => {
62                let msg = match e {
63                    arrow_schema::ArrowError::IoError(msg, _) => {
64                        static START: &str = "Code:";
65                        static END: &str = ". at";
66
67                        let message_index = msg.find(START).unwrap_or(0);
68                        let message_end_index = msg.find(END).unwrap_or(msg.len());
69                        let message = &msg[message_index..message_end_index];
70                        message.replace("\\n", "\n")
71                    }
72                    other => format!("{other}"),
73                };
74                format!("ArrowError: {msg}")
75            }
76            Error::Convert(e) => format!(
77                "ConvertError: cannot convert {} to {}: {:?}",
78                e.data, e.target, e.message
79            ),
80            Error::Api(e) => format!("APIError: {e}"),
81        }
82    }
83}
84
85impl std::fmt::Display for Error {
86    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87        write!(
88            f,
89            "{} [v{}]",
90            self.formatted_message(),
91            env!("CARGO_PKG_VERSION")
92        )
93    }
94}
95
96impl std::error::Error for Error {}
97
98pub type Result<T, E = Error> = core::result::Result<T, E>;
99
100impl From<url::ParseError> for Error {
101    fn from(e: url::ParseError) -> Self {
102        Error::Parsing(e.to_string())
103    }
104}
105
106impl From<std::num::ParseIntError> for Error {
107    fn from(e: std::num::ParseIntError) -> Self {
108        Error::Parsing(e.to_string())
109    }
110}
111
112impl From<std::str::ParseBoolError> for Error {
113    fn from(e: std::str::ParseBoolError) -> Self {
114        Error::Parsing(e.to_string())
115    }
116}
117
118impl From<std::num::ParseFloatError> for Error {
119    fn from(e: std::num::ParseFloatError) -> Self {
120        Error::Parsing(e.to_string())
121    }
122}
123
124impl From<chrono::ParseError> for Error {
125    fn from(e: chrono::ParseError) -> Self {
126        Error::Parsing(e.to_string())
127    }
128}
129
130impl From<std::io::Error> for Error {
131    fn from(e: std::io::Error) -> Self {
132        Error::IO(e.to_string())
133    }
134}
135
136impl From<glob::GlobError> for Error {
137    fn from(e: glob::GlobError) -> Self {
138        Error::IO(e.to_string())
139    }
140}
141
142impl From<glob::PatternError> for Error {
143    fn from(e: glob::PatternError) -> Self {
144        Error::Parsing(e.to_string())
145    }
146}
147
148#[cfg(feature = "flight-sql")]
149impl From<tonic::Status> for Error {
150    fn from(e: tonic::Status) -> Self {
151        Error::Protocol(e.to_string())
152    }
153}
154
155#[cfg(feature = "flight-sql")]
156impl From<tonic::transport::Error> for Error {
157    fn from(e: tonic::transport::Error) -> Self {
158        Error::Transport(e.to_string())
159    }
160}
161
162impl From<arrow_schema::ArrowError> for Error {
163    fn from(e: arrow_schema::ArrowError) -> Self {
164        Error::Arrow(e)
165    }
166}
167
168impl From<std::str::Utf8Error> for Error {
169    fn from(e: std::str::Utf8Error) -> Self {
170        Error::Parsing(e.to_string())
171    }
172}
173
174impl From<std::string::FromUtf8Error> for Error {
175    fn from(e: std::string::FromUtf8Error) -> Self {
176        Error::Parsing(e.to_string())
177    }
178}
179
180impl From<serde_json::Error> for Error {
181    fn from(e: serde_json::Error) -> Self {
182        Error::Parsing(e.to_string())
183    }
184}
185
186impl From<jiff::Error> for Error {
187    fn from(e: jiff::Error) -> Self {
188        Error::Parsing(e.to_string())
189    }
190}
191
192impl From<hex::FromHexError> for Error {
193    fn from(e: hex::FromHexError) -> Self {
194        Error::Parsing(e.to_string())
195    }
196}
197
198impl From<databend_client::Error> for Error {
199    fn from(e: databend_client::Error) -> Self {
200        Error::Api(e)
201    }
202}
203
204impl From<ConvertError> for Error {
205    fn from(e: ConvertError) -> Self {
206        Error::Convert(e)
207    }
208}
209
210impl From<GeozeroError> for Error {
211    fn from(e: GeozeroError) -> Self {
212        Error::Parsing(e.to_string())
213    }
214}