1use std::any::Any;
16
17use common_error::ext::{BoxedError, ErrorExt};
18use common_error::status_code::StatusCode;
19use common_macro::stack_trace_debug;
20use datatypes::prelude::ConcreteDataType;
21use snafu::{Location, Snafu};
22use store_api::region_request::RegionRequest;
23use store_api::storage::RegionId;
24
25#[derive(Snafu)]
26#[snafu(visibility(pub))]
27#[stack_trace_debug]
28pub enum Error {
29 #[snafu(display("Failed to create mito region, region type: {}", region_type))]
30 CreateMitoRegion {
31 region_type: String,
32 source: BoxedError,
33 #[snafu(implicit)]
34 location: Location,
35 },
36
37 #[snafu(display("Failed to open mito region, region type: {}", region_type))]
38 OpenMitoRegion {
39 region_type: String,
40 source: BoxedError,
41 #[snafu(implicit)]
42 location: Location,
43 },
44
45 #[snafu(display("Failed to batch open mito region"))]
46 BatchOpenMitoRegion {
47 source: BoxedError,
48 #[snafu(implicit)]
49 location: Location,
50 },
51
52 #[snafu(display("No open region result for region {}", region_id))]
53 NoOpenRegionResult {
54 region_id: RegionId,
55 #[snafu(implicit)]
56 location: Location,
57 },
58
59 #[snafu(display("Failed to close mito region, region id: {}", region_id))]
60 CloseMitoRegion {
61 region_id: RegionId,
62 source: BoxedError,
63 #[snafu(implicit)]
64 location: Location,
65 },
66
67 #[snafu(display("Failed to deserialize column metadata from {}", raw))]
68 DeserializeColumnMetadata {
69 raw: String,
70 #[snafu(source)]
71 error: serde_json::Error,
72 #[snafu(implicit)]
73 location: Location,
74 },
75
76 #[snafu(display("Failed to serialize column metadata"))]
77 SerializeColumnMetadata {
78 #[snafu(source)]
79 error: serde_json::Error,
80 #[snafu(implicit)]
81 location: Location,
82 },
83
84 #[snafu(display("Failed to serialize region manifest info"))]
85 SerializeRegionManifestInfo {
86 #[snafu(source)]
87 error: serde_json::Error,
88 #[snafu(implicit)]
89 location: Location,
90 },
91
92 #[snafu(display("Failed to decode base64 column value"))]
93 DecodeColumnValue {
94 #[snafu(source)]
95 error: base64::DecodeError,
96 #[snafu(implicit)]
97 location: Location,
98 },
99
100 #[snafu(display("Failed to parse region id from {}", raw))]
101 ParseRegionId {
102 raw: String,
103 #[snafu(source)]
104 error: <u64 as std::str::FromStr>::Err,
105 #[snafu(implicit)]
106 location: Location,
107 },
108
109 #[snafu(display("Failed to parse region options: {}", reason))]
110 ParseRegionOptions {
111 reason: String,
112 #[snafu(implicit)]
113 location: Location,
114 },
115
116 #[snafu(display("Mito read operation fails"))]
117 MitoReadOperation {
118 source: BoxedError,
119 #[snafu(implicit)]
120 location: Location,
121 },
122
123 #[snafu(display("Failed to encode primary key"))]
124 EncodePrimaryKey {
125 source: mito_codec::error::Error,
126 #[snafu(implicit)]
127 location: Location,
128 },
129
130 #[snafu(display("Mito write operation fails"))]
131 MitoWriteOperation {
132 source: BoxedError,
133 #[snafu(implicit)]
134 location: Location,
135 },
136
137 #[snafu(display("Mito flush operation fails"))]
138 MitoFlushOperation {
139 source: BoxedError,
140 #[snafu(implicit)]
141 location: Location,
142 },
143
144 #[snafu(display("Mito delete operation fails"))]
145 MitoDeleteOperation {
146 source: BoxedError,
147 #[snafu(implicit)]
148 location: Location,
149 },
150
151 #[snafu(display("Mito catchup operation fails"))]
152 MitoCatchupOperation {
153 source: BoxedError,
154 #[snafu(implicit)]
155 location: Location,
156 },
157
158 #[snafu(display("Mito sync operation fails"))]
159 MitoSyncOperation {
160 source: BoxedError,
161 #[snafu(implicit)]
162 location: Location,
163 },
164
165 #[snafu(display("Failed to collect record batch stream"))]
166 CollectRecordBatchStream {
167 source: common_recordbatch::error::Error,
168 #[snafu(implicit)]
169 location: Location,
170 },
171
172 #[snafu(display("Internal column {} is reserved", column))]
173 InternalColumnOccupied {
174 column: String,
175 #[snafu(implicit)]
176 location: Location,
177 },
178
179 #[snafu(display("Required table option is missing"))]
180 MissingRegionOption {
181 #[snafu(implicit)]
182 location: Location,
183 },
184
185 #[snafu(display("Region options are conflicted"))]
186 ConflictRegionOption {
187 #[snafu(implicit)]
188 location: Location,
189 },
190
191 #[snafu(display("Physical region {} not found", region_id))]
192 PhysicalRegionNotFound {
193 region_id: RegionId,
194 #[snafu(implicit)]
195 location: Location,
196 },
197
198 #[snafu(display("Logical region {} not found", region_id))]
199 LogicalRegionNotFound {
200 region_id: RegionId,
201 #[snafu(implicit)]
202 location: Location,
203 },
204
205 #[snafu(display("Column type mismatch. Expect {:?}, got {:?}", expect, actual))]
206 ColumnTypeMismatch {
207 expect: ConcreteDataType,
208 actual: ConcreteDataType,
209 #[snafu(implicit)]
210 location: Location,
211 },
212
213 #[snafu(display("Column {} not found in logical region {}", name, region_id))]
214 ColumnNotFound {
215 name: String,
216 region_id: RegionId,
217 #[snafu(implicit)]
218 location: Location,
219 },
220
221 #[snafu(display("Alter request to physical region is forbidden"))]
222 ForbiddenPhysicalAlter {
223 #[snafu(implicit)]
224 location: Location,
225 },
226
227 #[snafu(display("Invalid region metadata"))]
228 InvalidMetadata {
229 source: store_api::metadata::MetadataError,
230 #[snafu(implicit)]
231 location: Location,
232 },
233
234 #[snafu(display(
235 "Physical region {} is busy, there are still some logical regions using it",
236 region_id
237 ))]
238 PhysicalRegionBusy {
239 region_id: RegionId,
240 #[snafu(implicit)]
241 location: Location,
242 },
243
244 #[snafu(display("Unsupported region request: {}", request))]
245 UnsupportedRegionRequest {
246 request: Box<RegionRequest>,
247 #[snafu(implicit)]
248 location: Location,
249 },
250
251 #[snafu(display("Unsupported alter kind: {}", kind))]
252 UnsupportedAlterKind {
253 kind: String,
254 #[snafu(implicit)]
255 location: Location,
256 },
257
258 #[snafu(display("Multiple field column found: {} and {}", previous, current))]
259 MultipleFieldColumn {
260 previous: String,
261 current: String,
262 #[snafu(implicit)]
263 location: Location,
264 },
265
266 #[snafu(display("Adding field column {} to physical table", name))]
267 AddingFieldColumn {
268 name: String,
269 #[snafu(implicit)]
270 location: Location,
271 },
272
273 #[snafu(display("No field column found"))]
274 NoFieldColumn {
275 #[snafu(implicit)]
276 location: Location,
277 },
278
279 #[snafu(display("Failed to set SKIPPING index option"))]
280 SetSkippingIndexOption {
281 source: datatypes::error::Error,
282 #[snafu(implicit)]
283 location: Location,
284 },
285
286 #[snafu(display("Unexpected request: {}", reason))]
287 UnexpectedRequest {
288 reason: String,
289 #[snafu(implicit)]
290 location: Location,
291 },
292
293 #[snafu(display("Expected metric manifest info, region: {}", region_id))]
294 MetricManifestInfo {
295 region_id: RegionId,
296 #[snafu(implicit)]
297 location: Location,
298 },
299
300 #[snafu(display("Failed to start repeated task: {}", name))]
301 StartRepeatedTask {
302 name: String,
303 source: common_runtime::error::Error,
304 #[snafu(implicit)]
305 location: Location,
306 },
307}
308
309pub type Result<T, E = Error> = std::result::Result<T, E>;
310
311impl ErrorExt for Error {
312 fn status_code(&self) -> StatusCode {
313 use Error::*;
314
315 match self {
316 InternalColumnOccupied { .. }
317 | MissingRegionOption { .. }
318 | ConflictRegionOption { .. }
319 | ColumnTypeMismatch { .. }
320 | PhysicalRegionBusy { .. }
321 | MultipleFieldColumn { .. }
322 | NoFieldColumn { .. }
323 | AddingFieldColumn { .. }
324 | ParseRegionOptions { .. }
325 | UnexpectedRequest { .. }
326 | UnsupportedAlterKind { .. } => StatusCode::InvalidArguments,
327
328 ForbiddenPhysicalAlter { .. } | UnsupportedRegionRequest { .. } => {
329 StatusCode::Unsupported
330 }
331
332 DeserializeColumnMetadata { .. }
333 | SerializeColumnMetadata { .. }
334 | DecodeColumnValue { .. }
335 | ParseRegionId { .. }
336 | InvalidMetadata { .. }
337 | SetSkippingIndexOption { .. }
338 | SerializeRegionManifestInfo { .. }
339 | NoOpenRegionResult { .. } => StatusCode::Unexpected,
340
341 PhysicalRegionNotFound { .. } | LogicalRegionNotFound { .. } => {
342 StatusCode::RegionNotFound
343 }
344
345 ColumnNotFound { .. } => StatusCode::TableColumnNotFound,
346
347 CreateMitoRegion { source, .. }
348 | OpenMitoRegion { source, .. }
349 | CloseMitoRegion { source, .. }
350 | MitoReadOperation { source, .. }
351 | MitoWriteOperation { source, .. }
352 | MitoCatchupOperation { source, .. }
353 | MitoFlushOperation { source, .. }
354 | MitoDeleteOperation { source, .. }
355 | MitoSyncOperation { source, .. }
356 | BatchOpenMitoRegion { source, .. } => source.status_code(),
357
358 EncodePrimaryKey { source, .. } => source.status_code(),
359
360 CollectRecordBatchStream { source, .. } => source.status_code(),
361
362 StartRepeatedTask { source, .. } => source.status_code(),
363
364 MetricManifestInfo { .. } => StatusCode::Internal,
365 }
366 }
367
368 fn as_any(&self) -> &dyn Any {
369 self
370 }
371}