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