Skip to main content

cqlite_core/
error.rs

1//! Error types for CQLite
2
3use std::fmt;
4use thiserror::Error;
5
6/// Result type alias for CQLite operations
7pub type Result<T> = std::result::Result<T, Error>;
8
9/// Main error type for CQLite operations
10#[derive(Error, Debug)]
11pub enum Error {
12    /// I/O related errors
13    #[error("I/O error: {0}")]
14    Io(#[from] std::io::Error),
15
16    /// Serialization/deserialization errors
17    #[error("Serialization error: {message}")]
18    Serialization {
19        message: String,
20        #[source]
21        source: Option<Box<dyn std::error::Error + Send + Sync>>,
22    },
23
24    /// Data corruption errors
25    #[error("Data corruption: {0}")]
26    Corruption(String),
27
28    /// Schema validation errors
29    #[error("Schema error: {0}")]
30    Schema(String),
31
32    /// CQL parsing errors
33    #[error("CQL parse error: {0}")]
34    CqlParse(String),
35
36    /// Invalid format error (for SSTable parsing)
37    #[error("Invalid format: {0}")]
38    InvalidFormat(String),
39
40    /// Unsupported format error
41    #[error("Unsupported format: {0}")]
42    UnsupportedFormat(String),
43
44    /// Timeout error
45    #[error("Operation timeout: {0}")]
46    Timeout(String),
47
48    /// Invalid path error
49    #[error("Invalid path: {0}")]
50    InvalidPath(String),
51
52    /// Invalid state error
53    #[error("Invalid state: {0}")]
54    InvalidState(String),
55
56    /// Query execution errors
57    #[error("Query execution error: {0}")]
58    QueryExecution(String),
59
60    /// Type conversion errors
61    #[error("Type conversion error: {0}")]
62    TypeConversion(String),
63
64    /// Configuration errors
65    #[error("Configuration error: {0}")]
66    Configuration(String),
67
68    /// Storage engine errors
69    #[error("Storage error: {0}")]
70    Storage(String),
71
72    /// Memory management errors
73    #[error("Memory error: {0}")]
74    Memory(String),
75
76    /// Lock/concurrency errors
77    #[error("Concurrency error: {0}")]
78    Concurrency(String),
79
80    /// Write directory already locked by another process or Database instance
81    ///
82    /// Returned by `WriteEngine::new` when the advisory lock on `write_dir`
83    /// cannot be acquired because another `WriteEngine` (in this or another
84    /// process) already holds it.  Only one `Database` instance may hold a
85    /// `write_dir` at a time.
86    #[error(
87        "write_dir '{path}' is already locked by another process. \
88         Only one Database instance may hold a write_dir at a time."
89    )]
90    WriteDirLocked {
91        /// The path that could not be locked
92        path: String,
93    },
94
95    /// Resource not found
96    #[error("Not found: {0}")]
97    NotFound(String),
98
99    /// Table errors
100    #[error("Table error: {0}")]
101    Table(String),
102
103    /// Resource already exists
104    #[error("Already exists: {0}")]
105    AlreadyExists(String),
106
107    /// Invalid operation
108    #[error("Invalid operation: {0}")]
109    InvalidOperation(String),
110
111    /// Constraint violation
112    #[error("Constraint violation: {0}")]
113    ConstraintViolation(String),
114
115    /// Transaction errors
116    #[error("Transaction error: {0}")]
117    Transaction(String),
118
119    /// Index errors
120    #[error("Index error: {0}")]
121    Index(String),
122
123    /// Compaction errors
124    #[error("Compaction error: {0}")]
125    Compaction(String),
126
127    /// WASM-specific errors
128    #[cfg(target_arch = "wasm32")]
129    #[error("WASM error: {0}")]
130    Wasm(String),
131
132    /// Generic internal error
133    #[error("Internal error: {0}")]
134    Internal(String),
135
136    /// Parse error
137    #[error("Parse error: {0}")]
138    Parse(String),
139
140    /// Invalid input error
141    #[error("Invalid input: {0}")]
142    InvalidInput(String),
143
144    /// Unsupported query error
145    #[error("Unsupported query: {0}")]
146    UnsupportedQuery(String),
147}
148
149impl Error {
150    /// Create a serialization error
151    pub fn serialization(msg: impl Into<String>) -> Self {
152        Self::Serialization {
153            message: msg.into(),
154            source: None,
155        }
156    }
157
158    /// Create a corruption error
159    pub fn corruption(msg: impl Into<String>) -> Self {
160        Self::Corruption(msg.into())
161    }
162
163    /// Create a schema error
164    pub fn schema(msg: impl Into<String>) -> Self {
165        Self::Schema(msg.into())
166    }
167
168    /// Create a CQL parse error
169    pub fn cql_parse(msg: impl Into<String>) -> Self {
170        Self::CqlParse(msg.into())
171    }
172
173    /// Create an invalid format error
174    pub fn invalid_format(msg: impl Into<String>) -> Self {
175        Self::InvalidFormat(msg.into())
176    }
177
178    /// Create an unsupported format error
179    pub fn unsupported_format(msg: impl Into<String>) -> Self {
180        Self::UnsupportedFormat(msg.into())
181    }
182
183    /// Create an invalid path error
184    pub fn invalid_path(msg: impl Into<String>) -> Self {
185        Self::InvalidPath(msg.into())
186    }
187
188    /// Create an invalid state error
189    pub fn invalid_state(msg: impl Into<String>) -> Self {
190        Self::InvalidState(msg.into())
191    }
192
193    /// Create a query execution error
194    pub fn query_execution(msg: impl Into<String>) -> Self {
195        Self::QueryExecution(msg.into())
196    }
197
198    /// Create a type conversion error
199    pub fn type_conversion(msg: impl Into<String>) -> Self {
200        Self::TypeConversion(msg.into())
201    }
202
203    /// Create a configuration error
204    pub fn configuration(msg: impl Into<String>) -> Self {
205        Self::Configuration(msg.into())
206    }
207
208    /// Create a storage error
209    pub fn storage(msg: impl Into<String>) -> Self {
210        Self::Storage(msg.into())
211    }
212
213    /// Create a memory error
214    pub fn memory(msg: impl Into<String>) -> Self {
215        Self::Memory(msg.into())
216    }
217
218    /// Create a concurrency error
219    pub fn concurrency(msg: impl Into<String>) -> Self {
220        Self::Concurrency(msg.into())
221    }
222
223    /// Create a not found error
224    pub fn not_found(msg: impl Into<String>) -> Self {
225        Self::NotFound(msg.into())
226    }
227
228    /// Create an already exists error
229    pub fn already_exists(msg: impl Into<String>) -> Self {
230        Self::AlreadyExists(msg.into())
231    }
232
233    /// Create an invalid operation error
234    pub fn invalid_operation(msg: impl Into<String>) -> Self {
235        Self::InvalidOperation(msg.into())
236    }
237
238    /// Create a constraint violation error
239    pub fn constraint_violation(msg: impl Into<String>) -> Self {
240        Self::ConstraintViolation(msg.into())
241    }
242
243    /// Create a transaction error
244    pub fn transaction(msg: impl Into<String>) -> Self {
245        Self::Transaction(msg.into())
246    }
247
248    /// Create an index error
249    pub fn index(msg: impl Into<String>) -> Self {
250        Self::Index(msg.into())
251    }
252
253    /// Create a compaction error
254    pub fn compaction(msg: impl Into<String>) -> Self {
255        Self::Compaction(msg.into())
256    }
257
258    /// Create a WASM error
259    #[cfg(target_arch = "wasm32")]
260    pub fn wasm(msg: impl Into<String>) -> Self {
261        Self::Wasm(msg.into())
262    }
263
264    /// Create an internal error
265    pub fn internal(msg: impl Into<String>) -> Self {
266        Self::Internal(msg.into())
267    }
268
269    /// Create an invalid input error
270    pub fn invalid_input(msg: impl Into<String>) -> Self {
271        Self::InvalidInput(msg.into())
272    }
273
274    /// Create a parse error
275    pub fn parse(msg: impl Into<String>) -> Self {
276        Self::Parse(msg.into())
277    }
278
279    /// Create an unsupported query error
280    pub fn unsupported_query(msg: impl Into<String>) -> Self {
281        Self::UnsupportedQuery(msg.into())
282    }
283
284    /// Create a write-dir locked error
285    pub fn write_dir_locked(path: impl Into<String>) -> Self {
286        Self::WriteDirLocked { path: path.into() }
287    }
288
289    /// Create a table not found error
290    pub fn table_not_found(msg: impl Into<String>) -> Self {
291        Self::NotFound(format!("Table not found: {}", msg.into()))
292    }
293
294    /// Create an ambiguous table error
295    pub fn ambiguous_table(msg: impl Into<String>) -> Self {
296        Self::Table(format!("Ambiguous table reference: {}", msg.into()))
297    }
298
299    /// Check if this error is recoverable
300    pub fn is_recoverable(&self) -> bool {
301        match self {
302            // These errors are typically recoverable with retry
303            Error::Io(_) => true,
304            Error::Concurrency(_) => true,
305            Error::Memory(_) => true,
306
307            // These errors are typically not recoverable
308            Error::Corruption(_) => false,
309            Error::Schema(_) => false,
310            Error::CqlParse(_) => false,
311            Error::Configuration(_) => false,
312
313            // Context-dependent errors
314            Error::Storage(_) => true,
315            Error::QueryExecution(_) => false,
316            Error::TypeConversion(_) => false,
317            Error::NotFound(_) => false,
318            Error::AlreadyExists(_) => false,
319            Error::InvalidOperation(_) => false,
320            Error::ConstraintViolation(_) => false,
321            Error::Transaction(_) => true,
322            Error::Index(_) => true,
323            Error::Compaction(_) => true,
324
325            // New error types
326            Error::Table(_) => false,
327
328            // Write-dir lock conflict — not recoverable without releasing the lock
329            Error::WriteDirLocked { .. } => false,
330
331            #[cfg(target_arch = "wasm32")]
332            Error::Wasm(_) => false,
333
334            Error::Serialization { .. } => false,
335            Error::Internal(_) => false,
336            Error::Parse(_) => false,
337            Error::InvalidInput(_) => false,
338            Error::InvalidFormat(_) => false,
339            Error::UnsupportedFormat(_) => false,
340            Error::InvalidPath(_) => false,
341            Error::InvalidState(_) => false,
342            Error::Timeout(_) => false,
343            Error::UnsupportedQuery(_) => false,
344        }
345    }
346
347    /// Get the error category
348    pub fn category(&self) -> ErrorCategory {
349        match self {
350            Error::Io(_) => ErrorCategory::System,
351            Error::Serialization { .. } => ErrorCategory::Data,
352            Error::Corruption(_) => ErrorCategory::Data,
353            Error::Schema(_) => ErrorCategory::Schema,
354            Error::CqlParse(_) => ErrorCategory::Query,
355            Error::QueryExecution(_) => ErrorCategory::Query,
356            Error::TypeConversion(_) => ErrorCategory::Data,
357            Error::Configuration(_) => ErrorCategory::Configuration,
358            Error::Storage(_) => ErrorCategory::Storage,
359            Error::Memory(_) => ErrorCategory::System,
360            Error::Concurrency(_) => ErrorCategory::Concurrency,
361            Error::NotFound(_) => ErrorCategory::NotFound,
362            Error::AlreadyExists(_) => ErrorCategory::Conflict,
363            Error::InvalidOperation(_) => ErrorCategory::Logic,
364            Error::ConstraintViolation(_) => ErrorCategory::Constraint,
365            Error::Transaction(_) => ErrorCategory::Transaction,
366            Error::Index(_) => ErrorCategory::Storage,
367            Error::Compaction(_) => ErrorCategory::Storage,
368
369            // New error types
370            Error::Table(_) => ErrorCategory::Schema,
371
372            // Write-dir lock conflict
373            Error::WriteDirLocked { .. } => ErrorCategory::Concurrency,
374
375            #[cfg(target_arch = "wasm32")]
376            Error::Wasm(_) => ErrorCategory::Platform,
377
378            Error::Internal(_) => ErrorCategory::Internal,
379            Error::Parse(_) => ErrorCategory::Data,
380            Error::InvalidInput(_) => ErrorCategory::Data,
381            Error::InvalidFormat(_) => ErrorCategory::Data,
382            Error::UnsupportedFormat(_) => ErrorCategory::Data,
383            Error::InvalidPath(_) => ErrorCategory::System,
384            Error::InvalidState(_) => ErrorCategory::Logic,
385            Error::Timeout(_) => ErrorCategory::System,
386            Error::UnsupportedQuery(_) => ErrorCategory::Query,
387        }
388    }
389}
390
391/// Error categories for grouping related errors
392#[derive(Debug, Clone, Copy, PartialEq, Eq)]
393pub enum ErrorCategory {
394    /// System-level errors (I/O, memory, etc.)
395    System,
396    /// Data-related errors (corruption, serialization)
397    Data,
398    /// Schema-related errors
399    Schema,
400    /// Query-related errors (parsing, execution)
401    Query,
402    /// Configuration errors
403    Configuration,
404    /// Storage engine errors
405    Storage,
406    /// Concurrency-related errors
407    Concurrency,
408    /// Resource not found
409    NotFound,
410    /// Resource conflicts
411    Conflict,
412    /// Logic errors
413    Logic,
414    /// Constraint violations
415    Constraint,
416    /// Transaction errors
417    Transaction,
418    /// Platform-specific errors
419    Platform,
420    /// Internal errors
421    Internal,
422}
423
424impl fmt::Display for ErrorCategory {
425    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
426        let name = match self {
427            ErrorCategory::System => "System",
428            ErrorCategory::Data => "Data",
429            ErrorCategory::Schema => "Schema",
430            ErrorCategory::Query => "Query",
431            ErrorCategory::Configuration => "Configuration",
432            ErrorCategory::Storage => "Storage",
433            ErrorCategory::Concurrency => "Concurrency",
434            ErrorCategory::NotFound => "NotFound",
435            ErrorCategory::Conflict => "Conflict",
436            ErrorCategory::Logic => "Logic",
437            ErrorCategory::Constraint => "Constraint",
438            ErrorCategory::Transaction => "Transaction",
439            ErrorCategory::Platform => "Platform",
440            ErrorCategory::Internal => "Internal",
441        };
442        write!(f, "{}", name)
443    }
444}
445
446/// Convert from bincode errors
447impl From<bincode::Error> for Error {
448    fn from(err: bincode::Error) -> Self {
449        Error::Serialization {
450            message: err.to_string(),
451            source: Some(Box::new(err)),
452        }
453    }
454}
455
456/// Convert from serde_json errors
457impl From<serde_json::Error> for Error {
458    fn from(err: serde_json::Error) -> Self {
459        Error::Serialization {
460            message: err.to_string(),
461            source: Some(Box::new(err)),
462        }
463    }
464}
465
466/// Convert from nom errors
467impl<I> From<nom::Err<nom::error::Error<I>>> for Error
468where
469    I: std::fmt::Debug,
470{
471    fn from(err: nom::Err<nom::error::Error<I>>) -> Self {
472        Error::CqlParse(format!("Parse error: {:?}", err))
473    }
474}
475
476// Helper function to create custom parse error type
477pub type ParseResult<I, O> = nom::IResult<I, O, Error>;
478
479/// Custom error type for parsing operations
480#[derive(Debug, Clone)]
481pub struct ParseError {
482    pub message: String,
483}
484
485impl std::fmt::Display for ParseError {
486    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
487        write!(f, "{}", self.message)
488    }
489}
490
491impl std::error::Error for ParseError {}
492
493#[cfg(test)]
494mod tests {
495    use super::*;
496
497    #[test]
498    fn test_error_from_conversions() {
499        // Test bincode error conversion (covers line 399-400)
500        let io_err = std::io::Error::other("test error");
501        let bincode_err = bincode::Error::new(bincode::ErrorKind::Io(io_err));
502        let error = Error::from(bincode_err);
503        assert!(matches!(error, Error::Serialization { .. }));
504
505        // Test serde_json error conversion (covers line 406-407)
506        let json_err = serde_json::from_str::<serde_json::Value>("invalid json").unwrap_err();
507        let error = Error::from(json_err);
508        assert!(matches!(error, Error::Serialization { .. }));
509
510        // Test nom error conversion (covers line 416-417)
511        let nom_err = nom::Err::Error(nom::error::Error::new(
512            "test input",
513            nom::error::ErrorKind::Tag,
514        ));
515        let error = Error::from(nom_err);
516        assert!(matches!(error, Error::CqlParse(_)));
517    }
518
519    #[test]
520    fn test_parse_error_display() {
521        // Test ParseError Display implementation (covers line 431-432)
522        let parse_error = ParseError {
523            message: "test parse error".to_string(),
524        };
525        let display_str = format!("{}", parse_error);
526        assert_eq!(display_str, "test parse error");
527    }
528
529    #[test]
530    #[cfg(target_arch = "wasm32")]
531    fn test_wasm_error_creation() {
532        // Test WASM error creation (covers line 234-235)
533        let err = Error::wasm("WASM error");
534        assert!(matches!(err, Error::Wasm(_)));
535        assert!(!err.is_recoverable());
536        assert_eq!(err.category(), ErrorCategory::Platform);
537    }
538
539    #[test]
540    fn test_new_error_types_coverage() {
541        // Test Table error
542        let table_err = Error::Table("table error".to_string());
543        assert!(!table_err.is_recoverable());
544        assert_eq!(table_err.category(), ErrorCategory::Schema);
545    }
546
547    #[test]
548    fn test_error_creation() {
549        let err = Error::storage("test error");
550        assert!(matches!(err, Error::Storage(_)));
551        assert_eq!(err.to_string(), "Storage error: test error");
552    }
553
554    #[test]
555    fn test_error_categories() {
556        assert_eq!(Error::storage("test").category(), ErrorCategory::Storage);
557        assert_eq!(Error::schema("test").category(), ErrorCategory::Schema);
558        assert_eq!(Error::cql_parse("test").category(), ErrorCategory::Query);
559    }
560
561    #[test]
562    fn test_error_recoverability() {
563        assert!(Error::concurrency("test").is_recoverable());
564        assert!(!Error::corruption("test").is_recoverable());
565        assert!(!Error::schema("test").is_recoverable());
566    }
567
568    #[test]
569    fn test_all_error_constructors() {
570        // Test all error constructor methods for coverage
571        let _ = Error::serialization("test");
572        let _ = Error::corruption("test");
573        let _ = Error::schema("test");
574        let _ = Error::cql_parse("test");
575        let _ = Error::invalid_format("test");
576        let _ = Error::unsupported_format("test");
577        let _ = Error::invalid_path("test");
578        let _ = Error::invalid_state("test");
579        let _ = Error::query_execution("test");
580        let _ = Error::type_conversion("test");
581        let _ = Error::configuration("test");
582        let _ = Error::storage("test");
583        let _ = Error::memory("test");
584        let _ = Error::concurrency("test");
585        let _ = Error::not_found("test");
586        let _ = Error::already_exists("test");
587        let _ = Error::invalid_operation("test");
588        let _ = Error::constraint_violation("test");
589        let _ = Error::transaction("test");
590        let _ = Error::index("test");
591        let _ = Error::compaction("test");
592        let _ = Error::internal("test");
593        let _ = Error::invalid_input("test");
594        let _ = Error::parse("test");
595        let _ = Error::write_dir_locked("/tmp/test-dir");
596    }
597
598    #[test]
599    fn test_all_error_categories() {
600        // Test all error categories for coverage
601        assert_eq!(Error::serialization("test").category(), ErrorCategory::Data);
602        assert_eq!(Error::corruption("test").category(), ErrorCategory::Data);
603        assert_eq!(Error::cql_parse("test").category(), ErrorCategory::Query);
604        assert_eq!(
605            Error::invalid_format("test").category(),
606            ErrorCategory::Data
607        );
608        assert_eq!(
609            Error::unsupported_format("test").category(),
610            ErrorCategory::Data
611        );
612        assert_eq!(
613            Error::invalid_path("test").category(),
614            ErrorCategory::System
615        );
616        assert_eq!(
617            Error::invalid_state("test").category(),
618            ErrorCategory::Logic
619        );
620        assert_eq!(
621            Error::query_execution("test").category(),
622            ErrorCategory::Query
623        );
624        assert_eq!(
625            Error::type_conversion("test").category(),
626            ErrorCategory::Data
627        );
628        assert_eq!(
629            Error::configuration("test").category(),
630            ErrorCategory::Configuration
631        );
632        assert_eq!(Error::memory("test").category(), ErrorCategory::System);
633        assert_eq!(
634            Error::concurrency("test").category(),
635            ErrorCategory::Concurrency
636        );
637        assert_eq!(Error::not_found("test").category(), ErrorCategory::NotFound);
638        assert_eq!(
639            Error::already_exists("test").category(),
640            ErrorCategory::Conflict
641        );
642        assert_eq!(
643            Error::invalid_operation("test").category(),
644            ErrorCategory::Logic
645        );
646        assert_eq!(
647            Error::constraint_violation("test").category(),
648            ErrorCategory::Constraint
649        );
650        assert_eq!(
651            Error::transaction("test").category(),
652            ErrorCategory::Transaction
653        );
654        assert_eq!(Error::index("test").category(), ErrorCategory::Storage);
655        assert_eq!(Error::compaction("test").category(), ErrorCategory::Storage);
656        assert_eq!(Error::internal("test").category(), ErrorCategory::Internal);
657        assert_eq!(Error::invalid_input("test").category(), ErrorCategory::Data);
658        assert_eq!(Error::parse("test").category(), ErrorCategory::Data);
659        assert_eq!(
660            Error::write_dir_locked("/tmp/test").category(),
661            ErrorCategory::Concurrency
662        );
663    }
664
665    #[test]
666    fn test_all_error_recoverability() {
667        // Test recoverability for all error types
668        assert!(Error::memory("test").is_recoverable());
669        assert!(Error::storage("test").is_recoverable());
670        assert!(Error::transaction("test").is_recoverable());
671        assert!(Error::index("test").is_recoverable());
672        assert!(Error::compaction("test").is_recoverable());
673
674        assert!(!Error::serialization("test").is_recoverable());
675        assert!(!Error::cql_parse("test").is_recoverable());
676        assert!(!Error::invalid_format("test").is_recoverable());
677        assert!(!Error::unsupported_format("test").is_recoverable());
678        assert!(!Error::invalid_path("test").is_recoverable());
679        assert!(!Error::invalid_state("test").is_recoverable());
680        assert!(!Error::query_execution("test").is_recoverable());
681        assert!(!Error::type_conversion("test").is_recoverable());
682        assert!(!Error::configuration("test").is_recoverable());
683        assert!(!Error::not_found("test").is_recoverable());
684        assert!(!Error::already_exists("test").is_recoverable());
685        assert!(!Error::invalid_operation("test").is_recoverable());
686        assert!(!Error::constraint_violation("test").is_recoverable());
687        assert!(!Error::internal("test").is_recoverable());
688        assert!(!Error::invalid_input("test").is_recoverable());
689        assert!(!Error::parse("test").is_recoverable());
690        assert!(!Error::write_dir_locked("/tmp/test").is_recoverable());
691    }
692
693    #[test]
694    fn test_error_category_display() {
695        // Test ErrorCategory Display implementation
696        assert_eq!(ErrorCategory::System.to_string(), "System");
697        assert_eq!(ErrorCategory::Data.to_string(), "Data");
698        assert_eq!(ErrorCategory::Schema.to_string(), "Schema");
699        assert_eq!(ErrorCategory::Query.to_string(), "Query");
700        assert_eq!(ErrorCategory::Configuration.to_string(), "Configuration");
701        assert_eq!(ErrorCategory::Storage.to_string(), "Storage");
702        assert_eq!(ErrorCategory::Concurrency.to_string(), "Concurrency");
703        assert_eq!(ErrorCategory::NotFound.to_string(), "NotFound");
704        assert_eq!(ErrorCategory::Conflict.to_string(), "Conflict");
705        assert_eq!(ErrorCategory::Logic.to_string(), "Logic");
706        assert_eq!(ErrorCategory::Constraint.to_string(), "Constraint");
707        assert_eq!(ErrorCategory::Transaction.to_string(), "Transaction");
708        assert_eq!(ErrorCategory::Platform.to_string(), "Platform");
709        assert_eq!(ErrorCategory::Internal.to_string(), "Internal");
710    }
711
712    #[test]
713    fn test_error_from_io_error() {
714        // Test conversion from std::io::Error
715        let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
716        let cqlite_err: Error = io_err.into();
717        assert!(matches!(cqlite_err, Error::Io(_)));
718        assert_eq!(cqlite_err.category(), ErrorCategory::System);
719        assert!(cqlite_err.is_recoverable());
720    }
721
722    #[test]
723    fn test_result_type_alias() {
724        // Test the Result type alias
725        let success: Result<i32> = Ok(42);
726        let failure: Result<i32> = Err(Error::storage("test error"));
727
728        assert!(success.is_ok());
729        if let Ok(value) = success {
730            assert_eq!(value, 42);
731        }
732        assert!(failure.is_err());
733    }
734}