torrust_tracker/core/databases/
error.rs

1//! Database errors.
2//!
3//! This module contains the [Database errors](crate::core::databases::error::Error).
4use std::panic::Location;
5use std::sync::Arc;
6
7use r2d2_mysql::mysql::UrlError;
8use torrust_tracker_located_error::{DynError, Located, LocatedError};
9
10use super::driver::Driver;
11
12#[derive(thiserror::Error, Debug, Clone)]
13pub enum Error {
14    /// The query unexpectedly returned nothing.
15    #[error("The {driver} query unexpectedly returned nothing: {source}")]
16    QueryReturnedNoRows {
17        source: LocatedError<'static, dyn std::error::Error + Send + Sync>,
18        driver: Driver,
19    },
20
21    /// The query was malformed.
22    #[error("The {driver} query was malformed: {source}")]
23    InvalidQuery {
24        source: LocatedError<'static, dyn std::error::Error + Send + Sync>,
25        driver: Driver,
26    },
27
28    /// Unable to insert a record into the database
29    #[error("Unable to insert record into {driver} database, {location}")]
30    InsertFailed {
31        location: &'static Location<'static>,
32        driver: Driver,
33    },
34
35    /// Unable to delete a record into the database
36    #[error("Failed to remove record from {driver} database, error-code: {error_code}, {location}")]
37    DeleteFailed {
38        location: &'static Location<'static>,
39        error_code: usize,
40        driver: Driver,
41    },
42
43    /// Unable to connect to the database
44    #[error("Failed to connect to {driver} database: {source}")]
45    ConnectionError {
46        source: LocatedError<'static, UrlError>,
47        driver: Driver,
48    },
49
50    /// Unable to create a connection pool
51    #[error("Failed to create r2d2 {driver} connection pool: {source}")]
52    ConnectionPool {
53        source: LocatedError<'static, r2d2::Error>,
54        driver: Driver,
55    },
56}
57
58impl From<r2d2_sqlite::rusqlite::Error> for Error {
59    #[track_caller]
60    fn from(err: r2d2_sqlite::rusqlite::Error) -> Self {
61        match err {
62            r2d2_sqlite::rusqlite::Error::QueryReturnedNoRows => Error::QueryReturnedNoRows {
63                source: (Arc::new(err) as DynError).into(),
64                driver: Driver::Sqlite3,
65            },
66            _ => Error::InvalidQuery {
67                source: (Arc::new(err) as DynError).into(),
68                driver: Driver::Sqlite3,
69            },
70        }
71    }
72}
73
74impl From<r2d2_mysql::mysql::Error> for Error {
75    #[track_caller]
76    fn from(err: r2d2_mysql::mysql::Error) -> Self {
77        let e: DynError = Arc::new(err);
78        Error::InvalidQuery {
79            source: e.into(),
80            driver: Driver::MySQL,
81        }
82    }
83}
84
85impl From<UrlError> for Error {
86    #[track_caller]
87    fn from(err: UrlError) -> Self {
88        Self::ConnectionError {
89            source: Located(err).into(),
90            driver: Driver::MySQL,
91        }
92    }
93}
94
95impl From<(r2d2::Error, Driver)> for Error {
96    #[track_caller]
97    fn from(e: (r2d2::Error, Driver)) -> Self {
98        let (err, driver) = e;
99        Self::ConnectionPool {
100            source: Located(err).into(),
101            driver,
102        }
103    }
104}