alopex_sql/executor/
error.rs1use crate::executor::evaluator::VectorError;
9use crate::storage::StorageError;
10use thiserror::Error;
11
12#[derive(Debug, Error)]
14pub enum ExecutorError {
15 #[error("hnsw error: {0}")]
17 Core(#[from] alopex_core::Error),
18
19 #[error("table not found: {0}")]
21 TableNotFound(String),
22
23 #[error("table already exists: {0}")]
25 TableAlreadyExists(String),
26
27 #[error("index not found: {0}")]
29 IndexNotFound(String),
30
31 #[error("index already exists: {0}")]
33 IndexAlreadyExists(String),
34
35 #[error("column not found: {0}")]
37 ColumnNotFound(String),
38
39 #[error("constraint violation: {0}")]
41 ConstraintViolation(#[from] ConstraintViolation),
42
43 #[error("evaluation error: {0}")]
45 Evaluation(#[from] EvaluationError),
46
47 #[error("unsupported operation: {0}")]
49 UnsupportedOperation(String),
50
51 #[error("transaction conflict")]
53 TransactionConflict,
54
55 #[error("read-only transaction: cannot execute {operation}")]
57 ReadOnlyTransaction { operation: String },
58
59 #[error("storage error: {0}")]
61 Storage(#[from] StorageError),
62
63 #[error("column required: {column} (DEFAULT not supported in v0.1.2)")]
65 ColumnRequired { column: String },
66
67 #[error("invalid index name: {name} - {reason}")]
69 InvalidIndexName { name: String, reason: String },
70
71 #[error("invalid operation: {operation} - {reason}")]
73 InvalidOperation { operation: String, reason: String },
74
75 #[error("resource exhausted: {message}")]
77 ResourceExhausted { message: String },
78
79 #[error("file not found: {0}")]
81 FileNotFound(String),
82
83 #[error("path validation failed for '{path}': {reason}")]
85 PathValidationFailed { path: String, reason: String },
86
87 #[error("unsupported format: {0}")]
89 UnsupportedFormat(String),
90
91 #[error("schema mismatch: expected {expected} columns, got {actual} - {reason}")]
93 SchemaMismatch {
94 expected: usize,
95 actual: usize,
96 reason: String,
97 },
98
99 #[error("invalid storage type: {0}")]
101 InvalidStorageType(String),
102
103 #[error("invalid compression: {0}")]
105 InvalidCompression(String),
106
107 #[error("invalid row_group_size: {0}")]
109 InvalidRowGroupSize(String),
110
111 #[error("invalid rowid_mode: {0}")]
113 InvalidRowIdMode(String),
114
115 #[error("unknown table option: {0}")]
117 UnknownTableOption(String),
118
119 #[error("duplicate option: {0}")]
121 DuplicateOption(String),
122
123 #[error("vector error: {0}")]
125 Vector(#[from] VectorError),
126
127 #[error("bulk load error: {0}")]
129 BulkLoad(String),
130
131 #[error("columnar engine error: {0}")]
133 Columnar(String),
134
135 #[error("planner error: {0}")]
137 Planner(#[from] crate::planner::PlannerError),
138}
139
140#[derive(Debug, Error, Clone, PartialEq, Eq)]
142pub enum ConstraintViolation {
143 #[error("NOT NULL constraint violated on column: {column}")]
145 NotNull { column: String },
146
147 #[error("PRIMARY KEY constraint violated on columns: {columns:?}, value: {value:?}")]
149 PrimaryKey {
150 columns: Vec<String>,
151 value: Option<String>,
152 },
153
154 #[error(
156 "UNIQUE constraint violated on index: {index_name}, columns: {columns:?}, value: {value:?}"
157 )]
158 Unique {
159 index_name: String,
160 columns: Vec<String>,
161 value: Option<String>,
162 },
163}
164
165#[derive(Debug, Error, Clone, PartialEq, Eq)]
167pub enum EvaluationError {
168 #[error("division by zero")]
170 DivisionByZero,
171
172 #[error("integer overflow")]
174 Overflow,
175
176 #[error("type mismatch: expected {expected}, got {actual}")]
178 TypeMismatch { expected: String, actual: String },
179
180 #[error("invalid column reference: index {index}")]
182 InvalidColumnRef { index: usize },
183
184 #[error("unsupported expression: {0}")]
186 UnsupportedExpression(String),
187
188 #[error("unsupported function: {0}")]
190 UnsupportedFunction(String),
191
192 #[error("invalid regular expression '{pattern}': {reason}")]
194 InvalidRegex { pattern: String, reason: String },
195
196 #[error("invalid argument for {function}: {reason}")]
198 InvalidArgument { function: String, reason: String },
199
200 #[error("vector error: {0}")]
202 Vector(#[from] VectorError),
203}
204
205pub type Result<T> = std::result::Result<T, ExecutorError>;
207
208#[cfg(test)]
209mod tests {
210 use super::*;
211
212 #[test]
213 fn test_executor_error_display() {
214 let err = ExecutorError::TableNotFound("users".into());
215 assert_eq!(err.to_string(), "table not found: users");
216 }
217
218 #[test]
219 fn test_constraint_violation_display() {
220 let err = ConstraintViolation::NotNull {
221 column: "name".into(),
222 };
223 assert_eq!(
224 err.to_string(),
225 "NOT NULL constraint violated on column: name"
226 );
227 }
228
229 #[test]
230 fn test_evaluation_error_display() {
231 let err = EvaluationError::DivisionByZero;
232 assert_eq!(err.to_string(), "division by zero");
233 }
234
235 #[test]
236 fn test_constraint_violation_from() {
237 let violation = ConstraintViolation::NotNull {
238 column: "age".into(),
239 };
240 let err: ExecutorError = violation.into();
241 assert!(matches!(err, ExecutorError::ConstraintViolation(_)));
242 }
243
244 #[test]
245 fn test_evaluation_error_from() {
246 let eval_err = EvaluationError::Overflow;
247 let err: ExecutorError = eval_err.into();
248 assert!(matches!(err, ExecutorError::Evaluation(_)));
249 }
250
251 #[test]
252 fn test_vector_error_conversion() {
253 let vector_err = VectorError::ZeroNormVector;
254 let eval_err: EvaluationError = vector_err.clone().into();
255 assert!(matches!(eval_err, EvaluationError::Vector(_)));
256
257 let exec_err: ExecutorError = vector_err.into();
258 assert!(matches!(exec_err, ExecutorError::Vector(_)));
259 }
260
261 #[test]
262 fn test_path_validation_failed_display() {
263 let err = ExecutorError::PathValidationFailed {
264 path: "/tmp/data.parquet".into(),
265 reason: "symbolic links not allowed".into(),
266 };
267 assert_eq!(
268 err.to_string(),
269 "path validation failed for '/tmp/data.parquet': symbolic links not allowed"
270 );
271 }
272}