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