1pub use url::ParseError;
10
11mod tls;
12
13use mysql_common::{
14 named_params::MixedParamsError, params::MissingNamedParameterError,
15 proto::codec::error::PacketCodecError, row::Row, value::Value,
16};
17use thiserror::Error;
18
19use std::{io, result};
20
21pub type Result<T> = result::Result<T, Error>;
23
24#[derive(Debug, Error)]
26pub enum Error {
27 #[error("Driver error: `{}'", _0)]
28 Driver(#[source] DriverError),
29
30 #[error("Input/output error: {}", _0)]
31 Io(#[source] IoError),
32
33 #[error("Other error: {}", _0)]
34 Other(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
35
36 #[error("Server error: `{}'", _0)]
37 Server(#[source] ServerError),
38
39 #[error("URL error: `{}'", _0)]
40 Url(#[source] UrlError),
41}
42
43impl Error {
44 pub fn is_fatal(&self) -> bool {
46 match self {
47 Error::Driver(_) | Error::Io(_) | Error::Other(_) | Error::Url(_) => true,
48 Error::Server(_) => false,
49 }
50 }
51}
52
53#[derive(Debug, Error)]
55pub enum IoError {
56 #[error("Input/output error: {}", _0)]
57 Io(#[source] io::Error),
58 #[cfg(any(
59 feature = "native-tls-tls",
60 feature = "rustls-tls",
61 feature = "wasmedge-tls"
62 ))]
63 #[error("TLS error: `{}'", _0)]
64 Tls(#[source] tls::TlsError),
65}
66
67#[derive(Debug, Error, Clone, Eq, PartialEq)]
69#[error("ERROR {} ({}): {}", state, code, message)]
70pub struct ServerError {
71 pub code: u16,
72 pub message: String,
73 pub state: String,
74}
75
76#[derive(Debug, Error, Clone, Eq, PartialEq)]
78pub enum UrlError {
79 #[error("Connection URL parameter `{}' requires feature `{}'", param, feature)]
80 FeatureRequired { feature: String, param: String },
81
82 #[error("Invalid or incomplete connection URL")]
83 Invalid,
84
85 #[error("Invalid value `{}' for connection URL parameter `{}'", value, param)]
86 InvalidParamValue { param: String, value: String },
87
88 #[error("Invalid pool constraints: pool_min ({}) > pool_max ({}).", min, max)]
89 InvalidPoolConstraints { min: usize, max: usize },
90
91 #[error("URL parse error: {}", _0)]
92 Parse(#[source] ParseError),
93
94 #[error("Unknown connection URL parameter `{}'", param)]
95 UnknownParameter { param: String },
96
97 #[error("Unsupported connection URL scheme `{}'", scheme)]
98 UnsupportedScheme { scheme: String },
99}
100
101#[derive(Debug, Error)]
103pub enum DriverError {
104 #[error("Can't parse server version from string `{}'.", version_string)]
105 CantParseServerVersion { version_string: String },
106
107 #[error("Connection to the server is closed.")]
108 ConnectionClosed,
109
110 #[error("Error converting from mysql value.")]
111 FromValue { value: Value },
112
113 #[error("Error converting from mysql row.")]
114 FromRow { row: Row },
115
116 #[error("Missing named parameter `{}'.", String::from_utf8_lossy(name))]
117 MissingNamedParam { name: Vec<u8> },
118
119 #[error("Named and positional parameters mixed in one statement.")]
120 MixedParams,
121
122 #[error("Named parameters supplied for positional query.")]
123 NamedParamsForPositionalQuery,
124
125 #[error("Transactions couldn't be nested.")]
126 NestedTransaction,
127
128 #[error("Packet out of order.")]
129 PacketOutOfOrder,
130
131 #[error("Pool was disconnected.")]
132 PoolDisconnected,
133
134 #[error("`SET TRANSACTION READ (ONLY|WRITE)' is not supported in your MySQL version.")]
135 ReadOnlyTransNotSupported,
136
137 #[error(
138 "Statement takes {} parameters but {} was supplied.",
139 required,
140 supplied
141 )]
142 StmtParamsMismatch { required: u16, supplied: u16 },
143
144 #[error("Unexpected packet.")]
145 UnexpectedPacket { payload: Vec<u8> },
146
147 #[error("Unknown authentication plugin `{}'.", name)]
148 UnknownAuthPlugin { name: String },
149
150 #[error("Packet too large.")]
151 PacketTooLarge,
152
153 #[error("Bad compressed packet header.")]
154 BadCompressedPacketHeader,
155
156 #[error("Named pipe connections temporary disabled (see tokio-rs/tokio#3118)")]
157 NamedPipesDisabled,
158
159 #[error("`mysql_old_password` plugin is insecure and disabled by default")]
160 MysqlOldPasswordDisabled,
161
162 #[error("LOCAL INFILE error: {}", _0)]
163 LocalInfile(#[from] LocalInfileError),
164
165 #[error("No private key found in the file specified")]
166 NoKeyFound,
167
168 #[error("Client asked for SSL but server does not have this capability")]
169 NoClientSslFlagFromServer,
170
171 #[error("mysql_clear_password must be enabled on the client side")]
172 CleartextPluginDisabled,
173}
174
175#[derive(Debug, Error)]
176pub enum LocalInfileError {
177 #[error("The given path is not in the while list: {}", _0)]
178 PathIsNotInTheWhiteList(String),
179 #[error("Error reading `INFILE` data: {}", _0)]
180 ReadError(#[from] io::Error),
181 #[error("Can't handle local infile request. Handler is not specified.")]
182 NoHandler,
183 #[error(transparent)]
184 OtherError(Box<dyn std::error::Error + Send + Sync + 'static>),
185}
186
187impl LocalInfileError {
188 pub fn other<T>(err: T) -> Self
189 where
190 T: std::error::Error + Send + Sync + 'static,
191 {
192 Self::OtherError(Box::new(err))
193 }
194}
195
196impl From<LocalInfileError> for Error {
197 fn from(err: LocalInfileError) -> Self {
198 Self::Driver(err.into())
199 }
200}
201
202impl From<DriverError> for Error {
203 fn from(err: DriverError) -> Self {
204 Error::Driver(err)
205 }
206}
207
208impl From<IoError> for Error {
209 fn from(io: IoError) -> Self {
210 Error::Io(io)
211 }
212}
213
214impl From<io::Error> for IoError {
215 fn from(err: io::Error) -> Self {
216 IoError::Io(err)
217 }
218}
219
220impl From<io::Error> for Error {
221 fn from(err: io::Error) -> Self {
222 Error::Io(err.into())
223 }
224}
225
226impl From<ServerError> for Error {
227 fn from(err: ServerError) -> Self {
228 Error::Server(err)
229 }
230}
231
232impl From<UrlError> for Error {
233 fn from(err: UrlError) -> Self {
234 Error::Url(err)
235 }
236}
237
238#[cfg(feature = "native-tls-tls")]
239impl From<native_tls::Error> for IoError {
240 fn from(err: native_tls::Error) -> Self {
241 IoError::Tls(tls::TlsError::TlsError(err))
242 }
243}
244
245impl From<mysql_common::packets::ServerError<'_>> for ServerError {
246 fn from(packet: mysql_common::packets::ServerError<'_>) -> Self {
247 ServerError {
248 code: packet.error_code(),
249 message: packet.message_str().into(),
250 state: packet.sql_state_str().into(),
251 }
252 }
253}
254
255impl From<mysql_common::packets::ServerError<'_>> for Error {
256 fn from(packet: mysql_common::packets::ServerError<'_>) -> Self {
257 Error::Server(packet.into())
258 }
259}
260
261impl From<(Error, crate::io::Stream)> for Error {
263 fn from((err, _): (Error, crate::io::Stream)) -> Self {
264 err
265 }
266}
267
268impl From<MissingNamedParameterError> for DriverError {
269 fn from(err: MissingNamedParameterError) -> Self {
270 DriverError::MissingNamedParam { name: err.0 }
271 }
272}
273
274impl From<MissingNamedParameterError> for Error {
275 fn from(err: MissingNamedParameterError) -> Self {
276 Error::Driver(err.into())
277 }
278}
279
280impl From<MixedParamsError> for DriverError {
281 fn from(_err: MixedParamsError) -> Self {
282 DriverError::MixedParams
283 }
284}
285
286impl From<MixedParamsError> for Error {
287 fn from(err: MixedParamsError) -> Self {
288 Error::Driver(err.into())
289 }
290}
291
292impl From<ParseError> for UrlError {
293 fn from(err: ParseError) -> Self {
294 UrlError::Parse(err)
295 }
296}
297
298impl From<ParseError> for Error {
299 fn from(err: ParseError) -> Self {
300 Error::Url(err.into())
301 }
302}
303
304impl From<PacketCodecError> for IoError {
305 fn from(err: PacketCodecError) -> Self {
306 match err {
307 PacketCodecError::Io(err) => err.into(),
308 PacketCodecError::PacketTooLarge => {
309 io::Error::new(io::ErrorKind::Other, "packet too large").into()
310 }
311 PacketCodecError::PacketsOutOfSync => {
312 io::Error::new(io::ErrorKind::Other, "packet out of order").into()
313 }
314 PacketCodecError::BadCompressedPacketHeader => {
315 io::Error::new(io::ErrorKind::Other, "bad compressed packet header").into()
316 }
317 }
318 }
319}
320
321impl From<PacketCodecError> for Error {
322 fn from(err: PacketCodecError) -> Self {
323 Error::Io(err.into())
324 }
325}