1use std::any::Any;
16
17use common_error::ext::ErrorExt;
18use common_error::status_code::StatusCode;
19use common_macro::stack_trace_debug;
20use datafusion::arrow::error::ArrowError;
21use datafusion::error::DataFusionError;
22use serde_json::error::Error as JsonError;
23use snafu::{Location, Snafu};
24use store_api::storage::RegionId;
25
26#[derive(Snafu)]
27#[snafu(visibility(pub))]
28#[stack_trace_debug]
29pub enum Error {
30 #[snafu(display("Unsupported operation: {}", operation))]
31 Unsupported {
32 operation: String,
33 #[snafu(implicit)]
34 location: Location,
35 },
36
37 #[snafu(display("Unexpected engine: {}", engine))]
38 UnexpectedEngine {
39 engine: String,
40 #[snafu(implicit)]
41 location: Location,
42 },
43
44 #[snafu(display("Invalid region metadata"))]
45 InvalidMetadata {
46 source: store_api::metadata::MetadataError,
47 #[snafu(implicit)]
48 location: Location,
49 },
50
51 #[snafu(display("Region not found, region_id: {}", region_id))]
52 RegionNotFound {
53 region_id: RegionId,
54 #[snafu(implicit)]
55 location: Location,
56 },
57
58 #[snafu(display("Failed to check object from path: {}", path))]
59 CheckObject {
60 path: String,
61 #[snafu(implicit)]
62 location: Location,
63 #[snafu(source)]
64 error: object_store::Error,
65 },
66
67 #[snafu(display("Fail to encode object into json"))]
68 EncodeJson {
69 #[snafu(implicit)]
70 location: Location,
71 #[snafu(source)]
72 error: JsonError,
73 },
74
75 #[snafu(display("Fail to decode object from json"))]
76 DecodeJson {
77 #[snafu(implicit)]
78 location: Location,
79 #[snafu(source)]
80 error: JsonError,
81 },
82
83 #[snafu(display("Failed to store region manifest, region_id: {}", region_id))]
84 StoreRegionManifest {
85 #[snafu(source)]
86 error: object_store::Error,
87 region_id: RegionId,
88 #[snafu(implicit)]
89 location: Location,
90 },
91
92 #[snafu(display("Failed to load region manifest, region_id: {}", region_id))]
93 LoadRegionManifest {
94 #[snafu(source)]
95 error: object_store::Error,
96 region_id: RegionId,
97 #[snafu(implicit)]
98 location: Location,
99 },
100
101 #[snafu(display("Failed to delete region manifest, region_id: {},", region_id))]
102 DeleteRegionManifest {
103 #[snafu(source)]
104 error: object_store::Error,
105 region_id: RegionId,
106 #[snafu(implicit)]
107 location: Location,
108 },
109
110 #[snafu(display("Manifest already exists: {}", path))]
111 ManifestExists {
112 path: String,
113 #[snafu(implicit)]
114 location: Location,
115 },
116
117 #[snafu(display("Missing required field: {}", name))]
118 MissingRequiredField {
119 name: String,
120 #[snafu(implicit)]
121 location: Location,
122 },
123
124 #[snafu(display("Failed to build backend"))]
125 BuildBackend {
126 #[snafu(implicit)]
127 location: Location,
128 source: common_datasource::error::Error,
129 },
130
131 #[snafu(display("Failed to build stream"))]
132 BuildStream {
133 #[snafu(source)]
134 error: DataFusionError,
135 #[snafu(implicit)]
136 location: Location,
137 },
138
139 #[snafu(display("Failed to project schema"))]
140 ProjectArrowSchema {
141 #[snafu(source)]
142 error: ArrowError,
143 #[snafu(implicit)]
144 location: Location,
145 },
146
147 #[snafu(display("Failed to project schema"))]
148 ProjectSchema {
149 source: datatypes::error::Error,
150 #[snafu(implicit)]
151 location: Location,
152 },
153
154 #[snafu(display("Failed to build stream adapter"))]
155 BuildStreamAdapter {
156 #[snafu(implicit)]
157 location: Location,
158 source: common_recordbatch::error::Error,
159 },
160
161 #[snafu(display("Failed to parse file format"))]
162 ParseFileFormat {
163 #[snafu(implicit)]
164 location: Location,
165 source: common_datasource::error::Error,
166 },
167
168 #[snafu(display("Failed to generate parquet scan plan"))]
169 ParquetScanPlan {
170 #[snafu(source)]
171 error: DataFusionError,
172 #[snafu(implicit)]
173 location: Location,
174 },
175
176 #[snafu(display(
177 "Projection out of bounds, column_index: {}, bounds: {}",
178 column_index,
179 bounds
180 ))]
181 ProjectionOutOfBounds {
182 column_index: usize,
183 bounds: usize,
184 #[snafu(implicit)]
185 location: Location,
186 },
187
188 #[snafu(display("Failed to extract column from filter"))]
189 ExtractColumnFromFilter {
190 #[snafu(source)]
191 error: DataFusionError,
192 #[snafu(implicit)]
193 location: Location,
194 },
195
196 #[snafu(display("Failed to create default value for column: {}", column))]
197 CreateDefault {
198 column: String,
199 source: datatypes::error::Error,
200 #[snafu(implicit)]
201 location: Location,
202 },
203
204 #[snafu(display("Missing default value for column: {}", column))]
205 MissingColumnNoDefault {
206 column: String,
207 #[snafu(implicit)]
208 location: Location,
209 },
210}
211
212pub type Result<T> = std::result::Result<T, Error>;
213
214impl ErrorExt for Error {
215 fn status_code(&self) -> StatusCode {
216 use Error::*;
217
218 match self {
219 ProjectArrowSchema { .. }
220 | ProjectSchema { .. }
221 | MissingRequiredField { .. }
222 | Unsupported { .. }
223 | InvalidMetadata { .. }
224 | ProjectionOutOfBounds { .. }
225 | CreateDefault { .. }
226 | MissingColumnNoDefault { .. } => StatusCode::InvalidArguments,
227
228 RegionNotFound { .. } => StatusCode::RegionNotFound,
229
230 BuildBackend { source, .. } => source.status_code(),
231 BuildStreamAdapter { source, .. } => source.status_code(),
232 ParseFileFormat { source, .. } => source.status_code(),
233
234 CheckObject { .. }
235 | StoreRegionManifest { .. }
236 | LoadRegionManifest { .. }
237 | DeleteRegionManifest { .. } => StatusCode::StorageUnavailable,
238
239 EncodeJson { .. }
240 | DecodeJson { .. }
241 | ManifestExists { .. }
242 | BuildStream { .. }
243 | ParquetScanPlan { .. }
244 | UnexpectedEngine { .. }
245 | ExtractColumnFromFilter { .. } => StatusCode::Unexpected,
246 }
247 }
248
249 fn as_any(&self) -> &dyn Any {
250 self
251 }
252}
253
254impl From<Error> for common_procedure::Error {
255 fn from(e: Error) -> common_procedure::Error {
256 common_procedure::Error::from_error_ext(e)
257 }
258}