1use reifydb_type::{
5 error::{Diagnostic, Error, IntoDiagnostic},
6 fragment::Fragment,
7 value::r#type::Type,
8};
9
10#[derive(Debug, thiserror::Error)]
11pub enum ColumnError {
12 #[error("{operation}: column '{name}' not in schema")]
13 ColumnNotInSchema {
14 operation: &'static str,
15 name: String,
16 },
17
18 #[error("{operation}: only FixedArray storage supported in v1")]
19 FixedArrayRequired {
20 operation: &'static str,
21 },
22
23 #[error("take: indices must be a fixed-width integer array")]
24 TakeIndicesNotFixed,
25
26 #[error("take: indices must be U8/U16/U32/U64 or I32/I64")]
27 TakeIndicesWrongWidth,
28
29 #[error("Canonical::from_column_buffer: {variant} not yet supported")]
30 FromColumnDataUnsupported {
31 variant: &'static str,
32 },
33
34 #[error("Canonical::to_column_buffer: unexpected VarLen type {ty}")]
35 ToColumnDataUnexpectedVarLen {
36 ty: Type,
37 },
38
39 #[error("Canonical::to_column_buffer: unexpected BigNum type {ty}")]
40 ToColumnDataUnexpectedBigNum {
41 ty: Type,
42 },
43
44 #[error("Canonical::to_column_buffer: invalid UTF-8: {reason}")]
45 ToColumnDataInvalidUtf8 {
46 reason: String,
47 },
48
49 #[error("compare: column storage `{storage}` requires rhs `{expected}`")]
50 CompareRhsTypeMismatch {
51 storage: &'static str,
52 expected: &'static str,
53 },
54
55 #[error("compare: BigNum comparison not yet implemented")]
56 CompareBigNumUnsupported,
57
58 #[error("predicate::evaluate: compare did not return a bool array")]
59 PredicateCompareNotBool,
60
61 #[error("search_sorted: storage/needle type mismatch or unsupported")]
62 SearchSortedTypeMismatch,
63
64 #[error("min_max: empty array has no min/max")]
65 MinMaxEmpty,
66
67 #[error("min_max: all rows are None")]
68 MinMaxAllNone,
69
70 #[error("min_max: float min/max not yet implemented (NaN handling)")]
71 MinMaxFloatUnsupported,
72}
73
74impl From<ColumnError> for Error {
75 fn from(err: ColumnError) -> Self {
76 Error(Box::new(err.into_diagnostic()))
77 }
78}
79
80impl IntoDiagnostic for ColumnError {
81 fn into_diagnostic(self) -> Diagnostic {
82 match self {
83 ColumnError::ColumnNotInSchema {
84 operation,
85 name,
86 } => Diagnostic {
87 code: "COL_003".to_string(),
88 rql: None,
89 message: format!("{operation}: column '{name}' not in schema"),
90 column: None,
91 fragment: Fragment::None,
92 label: Some("column not found".to_string()),
93 help: Some("Verify the column name matches the block's schema".to_string()),
94 notes: vec![],
95 cause: None,
96 operator_chain: None,
97 },
98
99 ColumnError::FixedArrayRequired {
100 operation,
101 } => Diagnostic {
102 code: "COL_004".to_string(),
103 rql: None,
104 message: format!("{operation}: only FixedArray storage supported in v1"),
105 column: None,
106 fragment: Fragment::None,
107 label: None,
108 help: None,
109 notes: vec![],
110 cause: None,
111 operator_chain: None,
112 },
113
114 ColumnError::TakeIndicesNotFixed => Diagnostic {
115 code: "COL_005".to_string(),
116 rql: None,
117 message: "take: indices must be a fixed-width integer array".to_string(),
118 column: None,
119 fragment: Fragment::None,
120 label: None,
121 help: None,
122 notes: vec![],
123 cause: None,
124 operator_chain: None,
125 },
126
127 ColumnError::TakeIndicesWrongWidth => Diagnostic {
128 code: "COL_006".to_string(),
129 rql: None,
130 message: "take: indices must be U8/U16/U32/U64 or I32/I64".to_string(),
131 column: None,
132 fragment: Fragment::None,
133 label: None,
134 help: None,
135 notes: vec![],
136 cause: None,
137 operator_chain: None,
138 },
139
140 ColumnError::FromColumnDataUnsupported {
141 variant,
142 } => Diagnostic {
143 code: "COL_007".to_string(),
144 rql: None,
145 message: format!("Canonical::from_column_buffer: {variant} not yet supported"),
146 column: None,
147 fragment: Fragment::None,
148 label: Some(format!("{variant} column")),
149 help: None,
150 notes: vec![],
151 cause: None,
152 operator_chain: None,
153 },
154
155 ColumnError::ToColumnDataUnexpectedVarLen {
156 ty,
157 } => Diagnostic {
158 code: "COL_008".to_string(),
159 rql: None,
160 message: format!("Canonical::to_column_buffer: unexpected VarLen type {ty}"),
161 column: None,
162 fragment: Fragment::None,
163 label: None,
164 help: None,
165 notes: vec![],
166 cause: None,
167 operator_chain: None,
168 },
169
170 ColumnError::ToColumnDataUnexpectedBigNum {
171 ty,
172 } => Diagnostic {
173 code: "COL_009".to_string(),
174 rql: None,
175 message: format!("Canonical::to_column_buffer: unexpected BigNum type {ty}"),
176 column: None,
177 fragment: Fragment::None,
178 label: None,
179 help: None,
180 notes: vec![],
181 cause: None,
182 operator_chain: None,
183 },
184
185 ColumnError::ToColumnDataInvalidUtf8 {
186 reason,
187 } => Diagnostic {
188 code: "COL_010".to_string(),
189 rql: None,
190 message: format!("Canonical::to_column_buffer: invalid UTF-8: {reason}"),
191 column: None,
192 fragment: Fragment::None,
193 label: None,
194 help: None,
195 notes: vec![],
196 cause: None,
197 operator_chain: None,
198 },
199
200 ColumnError::CompareRhsTypeMismatch {
201 storage,
202 expected,
203 } => Diagnostic {
204 code: "COL_011".to_string(),
205 rql: None,
206 message: format!("compare: column storage `{storage}` requires rhs `{expected}`"),
207 column: None,
208 fragment: Fragment::None,
209 label: Some("rhs type mismatch".to_string()),
210 help: None,
211 notes: vec![],
212 cause: None,
213 operator_chain: None,
214 },
215
216 ColumnError::CompareBigNumUnsupported => Diagnostic {
217 code: "COL_012".to_string(),
218 rql: None,
219 message: "compare: BigNum comparison not yet implemented".to_string(),
220 column: None,
221 fragment: Fragment::None,
222 label: None,
223 help: None,
224 notes: vec![],
225 cause: None,
226 operator_chain: None,
227 },
228
229 ColumnError::PredicateCompareNotBool => Diagnostic {
230 code: "COL_013".to_string(),
231 rql: None,
232 message: "predicate::evaluate: compare did not return a bool array".to_string(),
233 column: None,
234 fragment: Fragment::None,
235 label: None,
236 help: None,
237 notes: vec![],
238 cause: None,
239 operator_chain: None,
240 },
241
242 ColumnError::SearchSortedTypeMismatch => Diagnostic {
243 code: "COL_014".to_string(),
244 rql: None,
245 message: "search_sorted: storage/needle type mismatch or unsupported".to_string(),
246 column: None,
247 fragment: Fragment::None,
248 label: None,
249 help: None,
250 notes: vec![],
251 cause: None,
252 operator_chain: None,
253 },
254
255 ColumnError::MinMaxEmpty => Diagnostic {
256 code: "COL_015".to_string(),
257 rql: None,
258 message: "min_max: empty array has no min/max".to_string(),
259 column: None,
260 fragment: Fragment::None,
261 label: None,
262 help: None,
263 notes: vec![],
264 cause: None,
265 operator_chain: None,
266 },
267
268 ColumnError::MinMaxAllNone => Diagnostic {
269 code: "COL_016".to_string(),
270 rql: None,
271 message: "min_max: all rows are None".to_string(),
272 column: None,
273 fragment: Fragment::None,
274 label: None,
275 help: None,
276 notes: vec![],
277 cause: None,
278 operator_chain: None,
279 },
280
281 ColumnError::MinMaxFloatUnsupported => Diagnostic {
282 code: "COL_017".to_string(),
283 rql: None,
284 message: "min_max: float min/max not yet implemented (NaN handling)".to_string(),
285 column: None,
286 fragment: Fragment::None,
287 label: None,
288 help: None,
289 notes: vec![],
290 cause: None,
291 operator_chain: None,
292 },
293 }
294 }
295}