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}