mysql_async/error/
mod.rs

1// Copyright (c) 2016 Anatoly Ikorsky
2//
3// Licensed under the Apache License, Version 2.0
4// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
5// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. All files in the project carrying such notice may not be copied,
7// modified, or distributed except according to those terms.
8
9pub 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
21/// Result type alias for this library.
22pub type Result<T> = result::Result<T, Error>;
23
24/// This type enumerates library errors.
25#[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    /// Returns true if the error means that connection is broken.
45    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/// This type enumerates IO errors.
54#[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/// This type represents MySql server error.
68#[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/// This type enumerates connection URL errors.
77#[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/// This type enumerates driver errors.
102#[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
261// For convenience
262impl 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}