Skip to main content

heliosdb_nano/
error.rs

1//! Error types for HeliosDB Lite
2//!
3//! This module defines all error types returned by HeliosDB Lite operations.
4//! All errors implement `std::error::Error` and can be displayed as human-readable
5//! messages.
6//!
7//! # Error Categories
8//!
9//! - **Storage errors**: RocksDB operations, disk I/O, corruption
10//! - **SQL errors**: Parsing, planning, and execution failures
11//! - **Transaction errors**: Conflicts, deadlocks, isolation violations
12//! - **Protocol errors**: Wire protocol issues, authentication failures
13//! - **Configuration errors**: Invalid settings, missing keys
14//!
15//! # Error Handling Example
16//!
17//! ```rust,no_run
18//! use heliosdb_nano::{EmbeddedDatabase, Error, Result};
19//!
20//! fn run_query(db: &EmbeddedDatabase, sql: &str) -> Result<()> {
21//!     match db.execute(sql) {
22//!         Ok(rows) => println!("Affected {} rows", rows),
23//!         Err(Error::SqlParse(msg)) => eprintln!("Syntax error: {}", msg),
24//!         Err(Error::QueryTimeout(msg)) => eprintln!("Query timed out: {}", msg),
25//!         Err(e) => eprintln!("Database error: {}", e),
26//!     }
27//!     Ok(())
28//! }
29//! ```
30
31/// Result type for HeliosDB operations
32///
33/// Alias for `std::result::Result<T, Error>` for convenience.
34pub type Result<T> = std::result::Result<T, Error>;
35
36/// Database error type
37///
38/// All errors from HeliosDB Lite operations are represented by this enum.
39/// Each variant includes a human-readable message describing the error.
40///
41/// # Creating Errors
42///
43/// Use the constructor methods for creating errors:
44///
45/// ```rust
46/// use heliosdb_nano::Error;
47///
48/// let err = Error::storage("Table not found: users");
49/// let err = Error::transaction("Deadlock detected");
50/// let err = Error::query_timeout("Query exceeded 30s limit");
51/// ```
52#[derive(Debug, thiserror::Error)]
53pub enum Error {
54    /// I/O error
55    #[error("I/O error: {0}")]
56    Io(#[from] std::io::Error),
57
58    /// Storage error
59    #[error("Storage error: {0}")]
60    Storage(String),
61
62    /// SQL parsing error
63    #[error("SQL parse error: {0}")]
64    SqlParse(String),
65
66    /// Query execution error
67    #[error("Query execution error: {0}")]
68    QueryExecution(String),
69
70    /// Query timeout error
71    #[error("Query timeout: {0}")]
72    QueryTimeout(String),
73
74    /// Query cancelled error
75    #[error("Query cancelled: {0}")]
76    QueryCancelled(String),
77
78    /// Transaction error
79    #[error("Transaction error: {0}")]
80    Transaction(String),
81
82    /// Type conversion error
83    #[error("Type conversion error: {0}")]
84    TypeConversion(String),
85
86    /// Invalid configuration
87    #[error("Invalid configuration: {0}")]
88    Config(String),
89
90    /// Encryption error
91    #[error("Encryption error: {0}")]
92    Encryption(String),
93
94    /// Protocol error
95    #[error("Protocol error: {0}")]
96    Protocol(String),
97
98    /// Vector index error
99    #[error("Vector index error: {0}")]
100    VectorIndex(String),
101
102    /// Multi-tenancy error
103    #[error("Multi-tenancy error: {0}")]
104    MultiTenant(String),
105
106    /// Audit error
107    #[error("Audit error: {0}")]
108    Audit(String),
109
110    /// Compression error
111    #[error("Compression error: {0}")]
112    Compression(String),
113
114    /// Branch merge error
115    #[error("Branch merge error: {0}")]
116    BranchMerge(String),
117
118    /// Merge conflict error
119    #[error("Merge conflict: {0}")]
120    MergeConflict(String),
121
122    /// Constraint violation error (FK, CHECK, UNIQUE)
123    #[error("Constraint violation: {0}")]
124    ConstraintViolation(String),
125
126    /// Lock poisoning error (mutex/rwlock poisoned)
127    #[error("Lock poisoning error: {0}")]
128    LockPoisoned(String),
129
130    /// Generic error
131    #[error("{0}")]
132    Generic(String),
133}
134
135impl Error {
136    /// Create a storage error
137    pub fn storage(msg: impl Into<String>) -> Self {
138        Error::Storage(msg.into())
139    }
140
141    /// Create a SQL parse error
142    pub fn sql_parse(msg: impl Into<String>) -> Self {
143        Error::SqlParse(msg.into())
144    }
145
146    /// Create a query execution error
147    pub fn query_execution(msg: impl Into<String>) -> Self {
148        Error::QueryExecution(msg.into())
149    }
150
151    /// Create a query timeout error
152    pub fn query_timeout(msg: impl Into<String>) -> Self {
153        Error::QueryTimeout(msg.into())
154    }
155
156    /// Create a query cancelled error
157    pub fn query_cancelled(msg: impl Into<String>) -> Self {
158        Error::QueryCancelled(msg.into())
159    }
160
161    /// Create a transaction error
162    pub fn transaction(msg: impl Into<String>) -> Self {
163        Error::Transaction(msg.into())
164    }
165
166    /// Create a type conversion error
167    pub fn type_conversion(msg: impl Into<String>) -> Self {
168        Error::TypeConversion(msg.into())
169    }
170
171    /// Create a config error
172    pub fn config(msg: impl Into<String>) -> Self {
173        Error::Config(msg.into())
174    }
175
176    /// Create an encryption error
177    pub fn encryption(msg: impl Into<String>) -> Self {
178        Error::Encryption(msg.into())
179    }
180
181    /// Create a protocol error
182    pub fn protocol(msg: impl Into<String>) -> Self {
183        Error::Protocol(msg.into())
184    }
185
186    /// Create a vector index error
187    pub fn vector_index(msg: impl Into<String>) -> Self {
188        Error::VectorIndex(msg.into())
189    }
190
191    /// Create a multi-tenant error
192    pub fn multi_tenant(msg: impl Into<String>) -> Self {
193        Error::MultiTenant(msg.into())
194    }
195
196    /// Create an audit error
197    pub fn audit(msg: impl Into<String>) -> Self {
198        Error::Audit(msg.into())
199    }
200
201    /// Create a compression error
202    pub fn compression(msg: impl Into<String>) -> Self {
203        Error::Compression(msg.into())
204    }
205
206    /// Create a branch merge error
207    pub fn branch_merge(msg: impl Into<String>) -> Self {
208        Error::BranchMerge(msg.into())
209    }
210
211    /// Create a merge conflict error
212    pub fn merge_conflict(msg: impl Into<String>) -> Self {
213        Error::MergeConflict(msg.into())
214    }
215
216    /// Create a constraint violation error (FK, CHECK, UNIQUE)
217    pub fn constraint_violation(msg: impl Into<String>) -> Self {
218        Error::ConstraintViolation(msg.into())
219    }
220
221    /// Create a network error
222    pub fn network(msg: impl Into<String>) -> Self {
223        Error::Protocol(msg.into())
224    }
225
226    /// Create an authentication error
227    pub fn authentication(msg: impl Into<String>) -> Self {
228        Error::Protocol(msg.into())
229    }
230
231    /// Create an I/O error from a message
232    pub fn io(msg: impl Into<String>) -> Self {
233        Error::Io(std::io::Error::new(std::io::ErrorKind::Other, msg.into()))
234    }
235
236    /// Create an internal error
237    pub fn internal(msg: impl Into<String>) -> Self {
238        Error::Generic(format!("Internal error: {}", msg.into()))
239    }
240
241    /// Create an execution error
242    pub fn execution(msg: impl Into<String>) -> Self {
243        Error::QueryExecution(msg.into())
244    }
245
246    /// Create a lock poisoning error
247    pub fn lock_poisoned(msg: impl Into<String>) -> Self {
248        Error::LockPoisoned(msg.into())
249    }
250
251    /// Create a resource limit error
252    pub fn resource_limit(msg: impl Into<String>) -> Self {
253        Error::Generic(format!("Resource limit exceeded: {}", msg.into()))
254    }
255
256    /// Create a deadlock error
257    pub fn deadlock(msg: impl Into<String>) -> Self {
258        Error::Transaction(format!("Deadlock: {}", msg.into()))
259    }
260
261    /// Create a high availability error
262    pub fn ha(msg: impl Into<String>) -> Self {
263        Error::Generic(format!("HA error: {}", msg.into()))
264    }
265
266    /// Create a switchover error
267    pub fn switchover(msg: impl Into<String>) -> Self {
268        Error::Generic(format!("Switchover error: {}", msg.into()))
269    }
270
271    /// Create a replication error
272    pub fn replication(msg: impl Into<String>) -> Self {
273        Error::Generic(format!("Replication error: {}", msg.into()))
274    }
275}
276
277/// Helper trait for converting PoisonError to our Error type
278pub trait LockResultExt<T> {
279    /// Convert a poisoned lock result into our Result type
280    fn map_lock_err(self, context: &str) -> Result<T>;
281}
282
283impl<T, E> LockResultExt<T> for std::result::Result<T, E>
284where
285    E: std::fmt::Display,
286{
287    fn map_lock_err(self, context: &str) -> Result<T> {
288        self.map_err(|e| Error::lock_poisoned(format!("{}: {}", context, e)))
289    }
290}
291
292// Implement conversions for common error types
293impl From<rocksdb::Error> for Error {
294    fn from(err: rocksdb::Error) -> Self {
295        Error::Storage(err.to_string())
296    }
297}
298
299impl From<sqlparser::parser::ParserError> for Error {
300    fn from(err: sqlparser::parser::ParserError) -> Self {
301        Error::SqlParse(err.to_string())
302    }
303}