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 std::sync::LazyLock;
16
17static ERROR_VERSION_SUFFIX: LazyLock<bool> =
18    LazyLock::new(|| std::env::var("BENDSQL_ERROR_NO_VERSION").is_err());
19
20#[derive(Debug)]
21pub struct ConvertError {
22    target: &'static str,
23    data: String,
24    message: Option<String>,
25}
26
27impl ConvertError {
28    pub fn new(target: &'static str, data: String) -> Self {
29        ConvertError {
30            target,
31            data,
32            message: None,
33        }
34    }
35
36    pub fn with_message(mut self, message: String) -> Self {
37        self.message = Some(message);
38        self
39    }
40}
41
42#[derive(Debug)]
43pub enum Error {
44    Parsing(String),
45    Protocol(String),
46    Transport(String),
47    IO(String),
48    BadArgument(String),
49    InvalidResponse(String),
50    Api(databend_client::Error),
51    Arrow(arrow_schema::ArrowError),
52    Convert(ConvertError),
53}
54
55impl Error {
56    fn formatted_message(&self) -> String {
57        match self {
58            Error::Parsing(msg) => format!("ParseError: {msg}"),
59            Error::Protocol(msg) => format!("ProtocolError: {msg}"),
60            Error::Transport(msg) => format!("TransportError: {msg}"),
61            Error::IO(msg) => format!("IOError: {msg}"),
62            Error::BadArgument(msg) => format!("BadArgument: {msg}"),
63            Error::InvalidResponse(msg) => format!("ResponseError: {msg}"),
64            Error::Arrow(e) => {
65                let msg = match e {
66                    arrow_schema::ArrowError::IoError(msg, _) => {
67                        static START: &str = "Code:";
68                        static END: &str = ". at";
69
70                        let message_index = msg.find(START).unwrap_or(0);
71                        let message_end_index = msg.find(END).unwrap_or(msg.len());
72                        let message = &msg[message_index..message_end_index];
73                        message.replace("\\n", "\n")
74                    }
75                    other => format!("{other}"),
76                };
77                format!("ArrowError: {msg}")
78            }
79            Error::Convert(e) => format!(
80                "ConvertError: cannot convert {} to {}: {:?}",
81                e.data, e.target, e.message
82            ),
83            Error::Api(e) => format!("APIError: {e}"),
84        }
85    }
86}
87
88impl std::fmt::Display for Error {
89    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90        let msg = self.formatted_message();
91        if *ERROR_VERSION_SUFFIX {
92            write!(f, "{msg} [v{}]", env!("CARGO_PKG_VERSION"))
93        } else {
94            write!(f, "{msg}")
95        }
96    }
97}
98
99impl std::error::Error for Error {}
100
101pub type Result<T, E = Error> = core::result::Result<T, E>;
102
103impl From<url::ParseError> for Error {
104    fn from(e: url::ParseError) -> Self {
105        Error::Parsing(e.to_string())
106    }
107}
108
109impl From<std::num::ParseIntError> for Error {
110    fn from(e: std::num::ParseIntError) -> Self {
111        Error::Parsing(e.to_string())
112    }
113}
114
115impl From<std::str::ParseBoolError> for Error {
116    fn from(e: std::str::ParseBoolError) -> Self {
117        Error::Parsing(e.to_string())
118    }
119}
120
121impl From<std::num::ParseFloatError> for Error {
122    fn from(e: std::num::ParseFloatError) -> Self {
123        Error::Parsing(e.to_string())
124    }
125}
126
127impl From<chrono::ParseError> for Error {
128    fn from(e: chrono::ParseError) -> Self {
129        Error::Parsing(e.to_string())
130    }
131}
132
133impl From<std::io::Error> for Error {
134    fn from(e: std::io::Error) -> Self {
135        Error::IO(e.to_string())
136    }
137}
138
139impl From<glob::GlobError> for Error {
140    fn from(e: glob::GlobError) -> Self {
141        Error::IO(e.to_string())
142    }
143}
144
145impl From<glob::PatternError> for Error {
146    fn from(e: glob::PatternError) -> Self {
147        Error::Parsing(e.to_string())
148    }
149}
150
151#[cfg(feature = "flight-sql")]
152impl From<tonic::Status> for Error {
153    fn from(e: tonic::Status) -> Self {
154        Error::Protocol(e.to_string())
155    }
156}
157
158#[cfg(feature = "flight-sql")]
159impl From<tonic::transport::Error> for Error {
160    fn from(e: tonic::transport::Error) -> Self {
161        Error::Transport(e.to_string())
162    }
163}
164
165impl From<arrow_schema::ArrowError> for Error {
166    fn from(e: arrow_schema::ArrowError) -> Self {
167        Error::Arrow(e)
168    }
169}
170
171impl From<std::str::Utf8Error> for Error {
172    fn from(e: std::str::Utf8Error) -> Self {
173        Error::Parsing(e.to_string())
174    }
175}
176
177impl From<std::string::FromUtf8Error> for Error {
178    fn from(e: std::string::FromUtf8Error) -> Self {
179        Error::Parsing(e.to_string())
180    }
181}
182
183impl From<serde_json::Error> for Error {
184    fn from(e: serde_json::Error) -> Self {
185        Error::Parsing(e.to_string())
186    }
187}
188
189impl From<jiff::Error> for Error {
190    fn from(e: jiff::Error) -> Self {
191        Error::Parsing(e.to_string())
192    }
193}
194
195impl From<hex::FromHexError> for Error {
196    fn from(e: hex::FromHexError) -> Self {
197        Error::Parsing(e.to_string())
198    }
199}
200
201impl From<databend_client::Error> for Error {
202    fn from(e: databend_client::Error) -> Self {
203        Error::Api(e)
204    }
205}
206
207impl From<ConvertError> for Error {
208    fn from(e: ConvertError) -> Self {
209        Error::Convert(e)
210    }
211}