clickhouse_readonly/
error.rs1use std::borrow::Cow;
2use std::io;
3use std::result;
4use std::str::Utf8Error;
5use std::string::FromUtf8Error;
6
7use thiserror::Error;
8use tokio::time::error::Elapsed;
9use url::ParseError;
10
11pub type ConnectionResult<T> = result::Result<T, ConnectionError>;
13pub type Result<T> = result::Result<T, Error>;
15
16#[derive(Debug, Error)]
18pub enum Error {
19 #[error("Driver error: `{}`", _0)]
20 Driver(#[source] DriverError),
21
22 #[error("Input/output error: `{}`", _0)]
23 IO(#[source] io::Error),
24
25 #[error("Connections error: `{}`", _0)]
26 Connection(#[source] ConnectionError),
27
28 #[error("Other error: `{}`", _0)]
29 Other(Cow<'static, str>),
30
31 #[error("Server error: `{}`", _0)]
32 Server(#[source] ServerError),
33
34 #[error("URL error: `{}`", _0)]
35 Url(#[source] UrlError),
36
37 #[error("From SQL error: `{}`", _0)]
38 FromSql(#[source] FromSqlError),
39}
40
41#[derive(Debug, Error, Clone)]
43#[error("ERROR {} ({:?}): {}", name, code, message)]
44pub struct ServerError {
45 pub code: u32,
46 pub name: String,
47 pub message: String,
48 pub stack_trace: String,
49}
50
51#[derive(Debug, Error)]
53pub enum ConnectionError {
54 #[error("TLS connection requires hostname to be provided")]
55 TlsHostNotProvided,
56
57 #[error("Input/output error: `{}`", _0)]
58 IOError(#[source] io::Error),
59
60 #[error("TLS connection error: `{}`", _0)]
61 TlsError(#[source] tokio_native_tls::native_tls::Error),
62}
63
64#[derive(Debug, Error, Clone)]
66pub enum UrlError {
67 #[error("Invalid or incomplete connection URL")]
68 Invalid,
69
70 #[error("Invalid value `{}' for connection URL parameter `{}'", value, param)]
71 InvalidParamValue { param: String, value: String },
72
73 #[error("URL parse error: {}", _0)]
74 Parse(#[source] ParseError),
75
76 #[error("Unknown connection URL parameter `{}'", param)]
77 UnknownParameter { param: String },
78
79 #[error("Unsupported connection URL scheme `{}'", scheme)]
80 UnsupportedScheme { scheme: String },
81}
82
83#[derive(Debug, Error, Clone)]
85pub enum DriverError {
86 #[error("Varint overflows a 64-bit integer.")]
87 Overflow,
88
89 #[error("Unknown packet 0x{:x}.", packet)]
90 UnknownPacket { packet: u64 },
91
92 #[error("Unexpected packet.")]
93 UnexpectedPacket,
94
95 #[error("Timeout error.")]
96 Timeout,
97
98 #[error("Invalid utf-8 sequence.")]
99 Utf8Error(Utf8Error),
100
101 #[error("UnknownSetting name {}", name)]
102 UnknownSetting { name: String },
103}
104
105#[derive(Debug, Error, Clone)]
107pub enum FromSqlError {
108 #[error("SqlType::{} cannot be cast to {}.", src, dst)]
109 InvalidType {
110 src: Cow<'static, str>,
111 dst: Cow<'static, str>,
112 },
113
114 #[error("Out of range.")]
115 OutOfRange,
116
117 #[error("Unsupported operation.")]
118 UnsupportedOperation,
119
120 #[error("Unsupported column type `{0}`.")]
121 UnsupportedColumnType(Cow<'static, str>),
122}
123
124impl Error {
125 pub(crate) fn is_would_block(&self) -> bool {
126 if let Error::IO(ref e) = self {
127 if e.kind() == io::ErrorKind::WouldBlock {
128 return true;
129 }
130 }
131 false
132 }
133}
134
135impl From<ConnectionError> for Error {
136 fn from(error: ConnectionError) -> Self {
137 Error::Connection(error)
138 }
139}
140
141impl From<tokio_native_tls::native_tls::Error> for ConnectionError {
142 fn from(error: tokio_native_tls::native_tls::Error) -> Self {
143 ConnectionError::TlsError(error)
144 }
145}
146
147impl From<DriverError> for Error {
148 fn from(err: DriverError) -> Self {
149 Error::Driver(err)
150 }
151}
152
153impl From<io::Error> for Error {
154 fn from(err: io::Error) -> Self {
155 Error::IO(err)
156 }
157}
158
159impl From<Error> for io::Error {
160 fn from(err: Error) -> Self {
161 match err {
162 Error::IO(error) => error,
163 e => io::Error::new(io::ErrorKind::Other, e.to_string()),
164 }
165 }
166}
167
168impl From<ServerError> for Error {
169 fn from(err: ServerError) -> Self {
170 Error::Server(err)
171 }
172}
173
174impl From<UrlError> for Error {
175 fn from(err: UrlError) -> Self {
176 Error::Url(err)
177 }
178}
179
180impl From<String> for Error {
181 fn from(err: String) -> Self {
182 Error::Other(Cow::from(err))
183 }
184}
185
186impl From<&str> for Error {
187 fn from(err: &str) -> Self {
188 Error::Other(err.to_string().into())
189 }
190}
191
192impl From<FromUtf8Error> for Error {
193 fn from(err: FromUtf8Error) -> Self {
194 Error::Other(err.to_string().into())
195 }
196}
197
198impl From<Elapsed> for Error {
199 fn from(_err: Elapsed) -> Self {
200 Error::Driver(DriverError::Timeout)
201 }
202}
203
204impl From<ParseError> for Error {
205 fn from(err: ParseError) -> Self {
206 Error::Url(UrlError::Parse(err))
207 }
208}
209
210impl From<Utf8Error> for Error {
211 fn from(err: Utf8Error) -> Self {
212 Error::Driver(DriverError::Utf8Error(err))
213 }
214}
215
216impl Error {
217 pub fn exception_name(&self) -> &str {
218 match self {
219 Error::Driver(_) => "DriverException",
220 Error::IO(_) => "IOException",
221 Error::Connection(_) => "ConnectionException",
222 Error::Other(_) => "OtherException",
223 Error::Server(e) => e.name.as_str(),
224 Error::Url(_) => "URLException",
225 Error::FromSql(_) => "SQLException",
226 }
227 }
228}