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("vector error: {0}")]
194 Vector(#[from] VectorError),
195}
196
197pub type Result<T> = std::result::Result<T, ExecutorError>;
199
200#[cfg(test)]
201mod tests {
202 use super::*;
203
204 #[test]
205 fn test_executor_error_display() {
206 let err = ExecutorError::TableNotFound("users".into());
207 assert_eq!(err.to_string(), "table not found: users");
208 }
209
210 #[test]
211 fn test_constraint_violation_display() {
212 let err = ConstraintViolation::NotNull {
213 column: "name".into(),
214 };
215 assert_eq!(
216 err.to_string(),
217 "NOT NULL constraint violated on column: name"
218 );
219 }
220
221 #[test]
222 fn test_evaluation_error_display() {
223 let err = EvaluationError::DivisionByZero;
224 assert_eq!(err.to_string(), "division by zero");
225 }
226
227 #[test]
228 fn test_constraint_violation_from() {
229 let violation = ConstraintViolation::NotNull {
230 column: "age".into(),
231 };
232 let err: ExecutorError = violation.into();
233 assert!(matches!(err, ExecutorError::ConstraintViolation(_)));
234 }
235
236 #[test]
237 fn test_evaluation_error_from() {
238 let eval_err = EvaluationError::Overflow;
239 let err: ExecutorError = eval_err.into();
240 assert!(matches!(err, ExecutorError::Evaluation(_)));
241 }
242
243 #[test]
244 fn test_vector_error_conversion() {
245 let vector_err = VectorError::ZeroNormVector;
246 let eval_err: EvaluationError = vector_err.clone().into();
247 assert!(matches!(eval_err, EvaluationError::Vector(_)));
248
249 let exec_err: ExecutorError = vector_err.into();
250 assert!(matches!(exec_err, ExecutorError::Vector(_)));
251 }
252
253 #[test]
254 fn test_path_validation_failed_display() {
255 let err = ExecutorError::PathValidationFailed {
256 path: "/tmp/data.parquet".into(),
257 reason: "symbolic links not allowed".into(),
258 };
259 assert_eq!(
260 err.to_string(),
261 "path validation failed for '/tmp/data.parquet': symbolic links not allowed"
262 );
263 }
264}