Skip to main content

clickhouse_driver/
errors.rs

1use std::str::Utf8Error;
2use std::{borrow::Cow, io, result};
3
4use thiserror::Error;
5use url::ParseError;
6
7use crate::types::SqlType;
8
9#[derive(Debug, Error, Clone, Eq, PartialEq)]
10#[error("{} {} {}", name, code, message)]
11pub struct Exception {
12    pub name: String,
13    pub code: u32,
14    pub message: String,
15    #[cfg(test)]
16    pub(crate) trace: String,
17}
18
19/// This type represents Clickhouse server error.
20#[derive(Debug, Error, Clone, Eq, PartialEq)]
21#[error("Server exception {}", _0[0])]
22pub struct ServerError(pub Box<[Exception]>);
23
24/// This type enumerates configuration URL errors.
25#[derive(Debug, Error, Clone, Eq, PartialEq)]
26pub enum UrlError {
27    #[error("Connection URL parameter `{}' requires feature `{}'", param, feature)]
28    FeatureRequired { feature: String, param: String },
29
30    #[error("Invalid or incomplete connection URL")]
31    Invalid,
32
33    #[error("Invalid value `{}' for connection URL parameter `{}'.", value, param)]
34    InvalidParamValue { param: String, value: String },
35
36    #[error("Invalid pool constraints: pool_min ({}) > pool_max ({}).", min, max)]
37    InvalidPoolConstraints { min: u16, max: u16 },
38
39    #[error("URL parse error: {}", _0)]
40    Parse(#[source] ParseError),
41
42    #[error("Unknown connection URL parameter `{}'.", param)]
43    UnknownParameter { param: String },
44
45    #[error("Unsupported connection URL scheme `{}'.", scheme)]
46    UnsupportedScheme { scheme: String },
47}
48
49/// This type enumerates clickhouse driver own errors.
50#[derive(Debug, Error, Clone, PartialEq)]
51pub enum DriverError {
52    #[error("Connection to the server is closed.")]
53    ConnectionClosed,
54
55    #[error("Connection timeout.")]
56    ConnectionTimeout,
57
58    #[error("Packet {} out of order.", _0)]
59    PacketOutOfOrder(u64),
60
61    #[error("Pool was disconnected.")]
62    PoolDisconnected,
63
64    #[error("Unexpected packet.")]
65    UnexpectedPacket { code: u64, payload: Vec<u8> },
66
67    #[error("Unsupported data type.")]
68    UnsupportedType(SqlType),
69
70    #[error("Malformed packet data.")]
71    BrokenData,
72
73    #[error("Packet too large.")]
74    PacketTooLarge,
75
76    #[error("String too long.")]
77    StringTooLong,
78
79    #[error("Bad compressed packet header.")]
80    BadCompressedPacketHeader,
81
82    #[error("Bad packet hash.")]
83    BadHash,
84
85    #[error("Block row count {} exceed the limit.", _0)]
86    RowCountTooMany(u64),
87
88    #[error("Other operation in progress.")]
89    OperationInProgress,
90
91    #[error("Index out of range.")]
92    IndexOutOfRange,
93
94    #[error("Integrity error")]
95    IntegrityError,
96}
97
98/// This type enumerates clickhouse data conversion  errors.
99#[derive(Debug, Error, Clone, PartialEq)]
100pub enum ConversionError {
101    #[error("Conversion unsupported")]
102    UnsupportedConversion,
103    #[error("fixed string length doesn't match column type. FixedString({})", _0)]
104    FixedStringLengthNotMatch(u32),
105    #[error("string value '{:?}' doesn't match enum value", _0)]
106    EnumMismatch(Vec<u8>),
107    #[error("Unknown column type '{}'", _0)]
108    UnknownColumnType(String),
109    #[error("Incorrect utf8 byte sequence")]
110    Utf8,
111}
112/// Consolidation of errors
113#[derive(Debug, Error)]
114pub enum Error {
115    #[error("Driver error: `{}'", _0)]
116    Driver(#[source] Box<DriverError>),
117
118    #[error("io error: `{}`", _0)]
119    Io(#[source] io::Error),
120
121    #[error("Server error: `{}'", _0)]
122    Server(#[source] ServerError),
123
124    #[error("URL error: `{}'", _0)]
125    Url(#[source] UrlError),
126
127    #[error("Deserialize error: `{}`", _0)]
128    Convertion(ConversionError),
129
130    #[error("Other error: `{}`", _0)]
131    Other(Cow<'static, str>),
132}
133
134impl Error {
135    pub fn is_timeout(&self) -> bool {
136        if let Error::Driver(berr) = self {
137            **berr == DriverError::ConnectionTimeout
138        } else {
139            false
140        }
141    }
142}
143
144pub type Result<T> = result::Result<T, Error>;
145
146impl From<io::Error> for Error {
147    fn from(err: io::Error) -> Self {
148        let kind = err.kind();
149        if err.get_ref().is_some() {
150            match err.into_inner().unwrap().downcast::<DriverError>() {
151                Ok(err) => Error::Driver(err),
152                _ => Error::Io(io::Error::from(kind)),
153            }
154        } else {
155            Error::Io(err)
156        }
157    }
158}
159
160impl From<Error> for io::Error {
161    fn from(err: Error) -> Self {
162        match err {
163            Error::Io(error) => error,
164            e => io::Error::new(io::ErrorKind::Other, e.to_string()),
165        }
166    }
167}
168
169impl From<ParseError> for UrlError {
170    fn from(err: ParseError) -> Self {
171        UrlError::Parse(err)
172    }
173}
174/// NotAnError
175impl From<std::convert::Infallible> for Error {
176    fn from(_: std::convert::Infallible) -> Self {
177        Error::Other(Cow::Borrowed(""))
178    }
179}
180
181impl From<ParseError> for Error {
182    fn from(err: ParseError) -> Self {
183        Error::Url(err.into())
184    }
185}
186
187impl From<Utf8Error> for Error {
188    fn from(_err: Utf8Error) -> Self {
189        Error::Convertion(ConversionError::Utf8)
190    }
191}
192
193impl From<DriverError> for Error {
194    fn from(err: DriverError) -> Self {
195        Error::Driver(Box::new(err))
196    }
197}
198
199impl From<ServerError> for Error {
200    fn from(err: ServerError) -> Self {
201        Error::Server(err)
202    }
203}
204
205impl From<UrlError> for Error {
206    fn from(err: UrlError) -> Self {
207        Error::Url(err)
208    }
209}
210
211impl From<ConversionError> for Error {
212    fn from(err: ConversionError) -> Self {
213        Error::Convertion(err)
214    }
215}
216
217impl From<&'static str> for Error {
218    fn from(err: &'static str) -> Self {
219        Error::Other(Cow::Borrowed(err))
220    }
221}
222
223impl From<()> for Error {
224    fn from(_err: ()) -> Self {
225        Error::Other(Cow::Borrowed("unknown error"))
226    }
227}