1use crate::ast::Span;
9use thiserror::Error;
10
11#[derive(Debug, Clone, PartialEq, Eq, Error)]
13pub enum PlannerError {
14 #[error("error[ALOPEX-C001]: table '{name}' not found at line {line}, column {column}")]
17 TableNotFound {
18 name: String,
19 line: u64,
20 column: u64,
21 },
22
23 #[error("error[ALOPEX-C002]: table '{name}' already exists")]
25 TableAlreadyExists { name: String },
26
27 #[error(
29 "error[ALOPEX-C003]: column '{column}' not found in table '{table}' at line {line}, column {col}"
30 )]
31 ColumnNotFound {
32 column: String,
33 table: String,
34 line: u64,
35 col: u64,
36 },
37
38 #[error(
40 "error[ALOPEX-C004]: ambiguous column '{column}' found in tables: {tables:?} at line {line}, column {col}"
41 )]
42 AmbiguousColumn {
43 column: String,
44 tables: Vec<String>,
45 line: u64,
46 col: u64,
47 },
48
49 #[error("error[ALOPEX-C005]: index '{name}' already exists")]
51 IndexAlreadyExists { name: String },
52
53 #[error("error[ALOPEX-C006]: index '{name}' not found")]
55 IndexNotFound { name: String },
56
57 #[error(
60 "error[ALOPEX-T001]: type mismatch at line {line}, column {column}: expected {expected}, found {found}"
61 )]
62 TypeMismatch {
63 expected: String,
64 found: String,
65 line: u64,
66 column: u64,
67 },
68
69 #[error(
71 "error[ALOPEX-T002]: invalid operator '{op}' for type '{type_name}' at line {line}, column {column}"
72 )]
73 InvalidOperator {
74 op: String,
75 type_name: String,
76 line: u64,
77 column: u64,
78 },
79
80 #[error(
82 "error[ALOPEX-T003]: null constraint violation for column '{column}' at line {line}, column {col}"
83 )]
84 NullConstraintViolation { column: String, line: u64, col: u64 },
85
86 #[error(
88 "error[ALOPEX-T004]: vector dimension mismatch at line {line}, column {column}: expected {expected}, found {found}"
89 )]
90 VectorDimensionMismatch {
91 expected: u32,
92 found: u32,
93 line: u64,
94 column: u64,
95 },
96
97 #[error(
99 "error[ALOPEX-T005]: invalid metric '{value}' at line {line}, column {column}. Valid options: cosine, l2, inner"
100 )]
101 InvalidMetric {
102 value: String,
103 line: u64,
104 column: u64,
105 },
106
107 #[error(
109 "error[ALOPEX-T006]: column count ({columns}) does not match value count ({values}) at line {line}, column {column}"
110 )]
111 ColumnValueCountMismatch {
112 columns: usize,
113 values: usize,
114 line: u64,
115 column: u64,
116 },
117
118 #[error(
121 "error[ALOPEX-F001]: feature '{feature}' is not supported in this version. Expected in {version}"
122 )]
123 UnsupportedFeature {
124 feature: String,
125 version: String,
126 line: u64,
127 column: u64,
128 },
129}
130
131impl PlannerError {
132 pub fn table_not_found(name: impl Into<String>, span: Span) -> Self {
134 Self::TableNotFound {
135 name: name.into(),
136 line: span.start.line,
137 column: span.start.column,
138 }
139 }
140
141 pub fn table_already_exists(name: impl Into<String>) -> Self {
143 Self::TableAlreadyExists { name: name.into() }
144 }
145
146 pub fn column_not_found(
148 column: impl Into<String>,
149 table: impl Into<String>,
150 span: Span,
151 ) -> Self {
152 Self::ColumnNotFound {
153 column: column.into(),
154 table: table.into(),
155 line: span.start.line,
156 col: span.start.column,
157 }
158 }
159
160 pub fn ambiguous_column(column: impl Into<String>, tables: Vec<String>, span: Span) -> Self {
162 Self::AmbiguousColumn {
163 column: column.into(),
164 tables,
165 line: span.start.line,
166 col: span.start.column,
167 }
168 }
169
170 pub fn index_already_exists(name: impl Into<String>) -> Self {
172 Self::IndexAlreadyExists { name: name.into() }
173 }
174
175 pub fn index_not_found(name: impl Into<String>) -> Self {
177 Self::IndexNotFound { name: name.into() }
178 }
179
180 pub fn type_mismatch(
182 expected: impl Into<String>,
183 found: impl Into<String>,
184 span: Span,
185 ) -> Self {
186 Self::TypeMismatch {
187 expected: expected.into(),
188 found: found.into(),
189 line: span.start.line,
190 column: span.start.column,
191 }
192 }
193
194 pub fn invalid_operator(
196 op: impl Into<String>,
197 type_name: impl Into<String>,
198 span: Span,
199 ) -> Self {
200 Self::InvalidOperator {
201 op: op.into(),
202 type_name: type_name.into(),
203 line: span.start.line,
204 column: span.start.column,
205 }
206 }
207
208 pub fn null_constraint_violation(column: impl Into<String>, span: Span) -> Self {
210 Self::NullConstraintViolation {
211 column: column.into(),
212 line: span.start.line,
213 col: span.start.column,
214 }
215 }
216
217 pub fn vector_dimension_mismatch(expected: u32, found: u32, span: Span) -> Self {
219 Self::VectorDimensionMismatch {
220 expected,
221 found,
222 line: span.start.line,
223 column: span.start.column,
224 }
225 }
226
227 pub fn invalid_metric(value: impl Into<String>, span: Span) -> Self {
229 Self::InvalidMetric {
230 value: value.into(),
231 line: span.start.line,
232 column: span.start.column,
233 }
234 }
235
236 pub fn column_value_count_mismatch(columns: usize, values: usize, span: Span) -> Self {
238 Self::ColumnValueCountMismatch {
239 columns,
240 values,
241 line: span.start.line,
242 column: span.start.column,
243 }
244 }
245
246 pub fn unsupported_feature(
248 feature: impl Into<String>,
249 version: impl Into<String>,
250 span: Span,
251 ) -> Self {
252 Self::UnsupportedFeature {
253 feature: feature.into(),
254 version: version.into(),
255 line: span.start.line,
256 column: span.start.column,
257 }
258 }
259}