file_engine/
error.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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}