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 parse file format"))]
155 ParseFileFormat {
156 #[snafu(implicit)]
157 location: Location,
158 source: common_datasource::error::Error,
159 },
160
161 #[snafu(display("Failed to generate parquet scan plan"))]
162 ParquetScanPlan {
163 #[snafu(source)]
164 error: DataFusionError,
165 #[snafu(implicit)]
166 location: Location,
167 },
168
169 #[snafu(display(
170 "Projection out of bounds, column_index: {}, bounds: {}",
171 column_index,
172 bounds
173 ))]
174 ProjectionOutOfBounds {
175 column_index: usize,
176 bounds: usize,
177 #[snafu(implicit)]
178 location: Location,
179 },
180
181 #[snafu(display("Failed to extract column from filter"))]
182 ExtractColumnFromFilter {
183 #[snafu(source)]
184 error: DataFusionError,
185 #[snafu(implicit)]
186 location: Location,
187 },
188
189 #[snafu(display("Failed to create default value for column: {}", column))]
190 CreateDefault {
191 column: String,
192 source: datatypes::error::Error,
193 #[snafu(implicit)]
194 location: Location,
195 },
196}
197
198pub type Result<T> = std::result::Result<T, Error>;
199
200impl ErrorExt for Error {
201 fn status_code(&self) -> StatusCode {
202 use Error::*;
203
204 match self {
205 ProjectArrowSchema { .. }
206 | ProjectSchema { .. }
207 | MissingRequiredField { .. }
208 | Unsupported { .. }
209 | InvalidMetadata { .. }
210 | ProjectionOutOfBounds { .. }
211 | CreateDefault { .. } => StatusCode::InvalidArguments,
212
213 RegionNotFound { .. } => StatusCode::RegionNotFound,
214
215 BuildBackend { source, .. } => source.status_code(),
216 ParseFileFormat { source, .. } => source.status_code(),
217
218 CheckObject { .. }
219 | StoreRegionManifest { .. }
220 | LoadRegionManifest { .. }
221 | DeleteRegionManifest { .. } => StatusCode::StorageUnavailable,
222
223 EncodeJson { .. }
224 | DecodeJson { .. }
225 | ManifestExists { .. }
226 | BuildStream { .. }
227 | ParquetScanPlan { .. }
228 | UnexpectedEngine { .. }
229 | ExtractColumnFromFilter { .. } => StatusCode::Unexpected,
230 }
231 }
232
233 fn as_any(&self) -> &dyn Any {
234 self
235 }
236}
237
238impl From<Error> for common_procedure::Error {
239 fn from(e: Error) -> common_procedure::Error {
240 common_procedure::Error::from_error_ext(e)
241 }
242}