audb_runtime/
error.rs

1//! Error types for AuDB runtime
2//!
3//! This module defines the error types used throughout the runtime library.
4
5use thiserror::Error;
6
7/// Errors that can occur during query execution
8///
9/// This enum covers all possible runtime errors including connection issues,
10/// query execution failures, type mismatches, and more.
11#[derive(Error, Debug)]
12pub enum QueryError {
13    /// Database connection error
14    #[error("Connection error: {message}")]
15    ConnectionError { message: String },
16
17    /// Query execution error
18    #[error("Query execution failed: {message}")]
19    ExecutionError { message: String },
20
21    /// Query parsing error (should be rare, as parsing is done at compile time)
22    #[error("Query parsing error: {message}")]
23    ParseError { message: String },
24
25    /// Type mismatch during result deserialization
26    #[error("Type mismatch: expected {expected}, got {actual}")]
27    TypeMismatch { expected: String, actual: String },
28
29    /// Missing required field in result
30    #[error("Missing required field: {field}")]
31    MissingField { field: String },
32
33    /// Transaction error
34    #[error("Transaction error: {message}")]
35    TransactionError { message: String },
36
37    /// Unsupported query language
38    #[error("Unsupported query language: {language}")]
39    UnsupportedLanguage { language: String },
40
41    /// Invalid parameter binding
42    #[error("Invalid parameter binding: {message}")]
43    ParameterError { message: String },
44
45    /// Row not found
46    #[error("Row not found")]
47    RowNotFound,
48
49    /// Multiple rows found when one was expected
50    #[error("Expected one row, found {count}")]
51    MultipleRowsFound { count: usize },
52
53    /// I/O error
54    #[error("I/O error: {0}")]
55    IoError(#[from] std::io::Error),
56
57    /// Serialization/deserialization error
58    #[error("Serialization error: {message}")]
59    SerializationError { message: String },
60
61    /// Generic error for cases not covered above
62    #[error("{0}")]
63    Other(String),
64}
65
66impl QueryError {
67    /// Create a connection error
68    pub fn connection<S: Into<String>>(message: S) -> Self {
69        QueryError::ConnectionError {
70            message: message.into(),
71        }
72    }
73
74    /// Create an execution error
75    pub fn execution<S: Into<String>>(message: S) -> Self {
76        QueryError::ExecutionError {
77            message: message.into(),
78        }
79    }
80
81    /// Create a parse error
82    pub fn parse<S: Into<String>>(message: S) -> Self {
83        QueryError::ParseError {
84            message: message.into(),
85        }
86    }
87
88    /// Create a type mismatch error
89    pub fn type_mismatch<S: Into<String>>(expected: S, actual: S) -> Self {
90        QueryError::TypeMismatch {
91            expected: expected.into(),
92            actual: actual.into(),
93        }
94    }
95
96    /// Create a missing field error
97    pub fn missing_field<S: Into<String>>(field: S) -> Self {
98        QueryError::MissingField {
99            field: field.into(),
100        }
101    }
102
103    /// Create a transaction error
104    pub fn transaction<S: Into<String>>(message: S) -> Self {
105        QueryError::TransactionError {
106            message: message.into(),
107        }
108    }
109
110    /// Create a parameter error
111    pub fn parameter<S: Into<String>>(message: S) -> Self {
112        QueryError::ParameterError {
113            message: message.into(),
114        }
115    }
116
117    /// Create a serialization error
118    pub fn serialization<S: Into<String>>(message: S) -> Self {
119        QueryError::SerializationError {
120            message: message.into(),
121        }
122    }
123
124    /// Create a generic error
125    pub fn other<S: Into<String>>(message: S) -> Self {
126        QueryError::Other(message.into())
127    }
128}
129
130/// Alias for Result with QueryError
131pub type Result<T> = std::result::Result<T, QueryError>;
132
133#[cfg(test)]
134mod tests {
135    use super::*;
136
137    #[test]
138    fn test_connection_error() {
139        let err = QueryError::connection("Failed to connect");
140        assert!(matches!(err, QueryError::ConnectionError { .. }));
141        assert_eq!(err.to_string(), "Connection error: Failed to connect");
142    }
143
144    #[test]
145    fn test_execution_error() {
146        let err = QueryError::execution("Query failed");
147        assert!(matches!(err, QueryError::ExecutionError { .. }));
148    }
149
150    #[test]
151    fn test_type_mismatch() {
152        let err = QueryError::type_mismatch("String", "Integer");
153        assert!(matches!(err, QueryError::TypeMismatch { .. }));
154        assert!(err.to_string().contains("String"));
155        assert!(err.to_string().contains("Integer"));
156    }
157
158    #[test]
159    fn test_missing_field() {
160        let err = QueryError::missing_field("id");
161        assert!(matches!(err, QueryError::MissingField { .. }));
162        assert!(err.to_string().contains("id"));
163    }
164
165    #[test]
166    fn test_row_not_found() {
167        let err = QueryError::RowNotFound;
168        assert_eq!(err.to_string(), "Row not found");
169    }
170
171    #[test]
172    fn test_multiple_rows_found() {
173        let err = QueryError::MultipleRowsFound { count: 5 };
174        assert!(err.to_string().contains("5"));
175    }
176
177    #[test]
178    fn test_unsupported_language() {
179        let err = QueryError::UnsupportedLanguage {
180            language: "gremlin".to_string(),
181        };
182        assert!(err.to_string().contains("gremlin"));
183    }
184
185    #[test]
186    fn test_io_error_conversion() {
187        let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
188        let err: QueryError = io_err.into();
189        assert!(matches!(err, QueryError::IoError(_)));
190    }
191
192    #[test]
193    fn test_result_alias() {
194        let ok_result: Result<i32> = Ok(42);
195        assert!(ok_result.is_ok());
196
197        let err_result: Result<i32> = Err(QueryError::RowNotFound);
198        assert!(err_result.is_err());
199    }
200}