Skip to main content

candybase/
error.rs

1//! # Error Types
2//!
3//! All Candy functions return `Result<T, CandyError>`.
4//! Match on the variant to distinguish connection errors from query errors.
5//!
6//! ```rust,ignore
7//! use candybase::{CandyError, candy_connect};
8//!
9//! match candy_connect("localhost", "root", "secret", "mydb") {
10//!     Ok(conn) => { /* use conn */ }
11//!     Err(CandyError::Connection(msg)) => eprintln!("Cannot connect: {}", msg),
12//!     Err(e) => eprintln!("Other error: {}", e),
13//! }
14//! ```
15
16use thiserror::Error;
17
18/// The unified error type for every Candy operation.
19///
20/// Every variant carries a descriptive `String` message so you can log or
21/// display it without additional context.
22#[derive(Debug, Error)]
23pub enum CandyError {
24    /// Returned when the initial database connection cannot be established.
25    ///
26    /// Common causes: wrong host/port, bad credentials, network firewall.
27    #[error("Connection error: {0}")]
28    Connection(String),
29
30    /// Returned when a SQL statement fails to execute.
31    ///
32    /// The message includes the driver-level error for easy debugging.
33    #[error("Query error: {0}")]
34    Query(String),
35
36    /// Returned when row data cannot be decoded into a `HashMap<String, String>`.
37    #[error("Fetch error: {0}")]
38    Fetch(String),
39
40    /// Returned when an atomic transaction cannot be completed.
41    ///
42    /// The whole transaction is rolled back automatically before this error
43    /// is returned.
44    #[error("Transaction error: {0}")]
45    Transaction(String),
46
47    /// Returned when the connection URL or DSN cannot be parsed.
48    #[error("URL parse error: {0}")]
49    UrlParse(String),
50
51    /// Returned for any other unexpected internal error.
52    #[error("Internal error: {0}")]
53    Internal(String),
54}
55
56// ── Blanket conversions from driver-specific errors ─────────────────────────
57
58#[cfg(feature = "mysql")]
59impl From<::mysql::Error> for CandyError {
60    fn from(e: ::mysql::Error) -> Self {
61        CandyError::Query(e.to_string())
62    }
63}
64
65#[cfg(feature = "postgres")]
66impl From<::postgres::Error> for CandyError {
67    fn from(e: ::postgres::Error) -> Self {
68        CandyError::Query(e.to_string())
69    }
70}
71
72#[cfg(feature = "sqlite")]
73impl From<::rusqlite::Error> for CandyError {
74    fn from(e: ::rusqlite::Error) -> Self {
75        CandyError::Query(e.to_string())
76    }
77}