cli/
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::{BoxedError, ErrorExt};
18use common_error::status_code::StatusCode;
19use common_macro::stack_trace_debug;
20use common_meta::peer::Peer;
21use object_store::Error as ObjectStoreError;
22use snafu::{Location, Snafu};
23use store_api::storage::TableId;
24
25#[derive(Snafu)]
26#[snafu(visibility(pub))]
27#[stack_trace_debug]
28pub enum Error {
29    #[snafu(display("Failed to install ring crypto provider: {}", msg))]
30    InitTlsProvider {
31        #[snafu(implicit)]
32        location: Location,
33        msg: String,
34    },
35
36    #[snafu(display("Failed to create default catalog and schema"))]
37    InitMetadata {
38        #[snafu(implicit)]
39        location: Location,
40        source: common_meta::error::Error,
41    },
42
43    #[snafu(display("Failed to init DDL manager"))]
44    InitDdlManager {
45        #[snafu(implicit)]
46        location: Location,
47        source: common_meta::error::Error,
48    },
49
50    #[snafu(display("Failed to init default timezone"))]
51    InitTimezone {
52        #[snafu(implicit)]
53        location: Location,
54        source: common_time::error::Error,
55    },
56
57    #[snafu(display("Failed to start procedure manager"))]
58    StartProcedureManager {
59        #[snafu(implicit)]
60        location: Location,
61        source: common_procedure::error::Error,
62    },
63
64    #[snafu(display("Failed to stop procedure manager"))]
65    StopProcedureManager {
66        #[snafu(implicit)]
67        location: Location,
68        source: common_procedure::error::Error,
69    },
70
71    #[snafu(display("Failed to start wal options allocator"))]
72    StartWalOptionsAllocator {
73        #[snafu(implicit)]
74        location: Location,
75        source: common_meta::error::Error,
76    },
77
78    #[snafu(display("Failed to get table metadata"))]
79    TableMetadata {
80        #[snafu(implicit)]
81        location: Location,
82        source: common_meta::error::Error,
83    },
84
85    #[snafu(display("Unexpected error: {}", msg))]
86    Unexpected {
87        msg: String,
88        #[snafu(implicit)]
89        location: Location,
90    },
91
92    #[snafu(display("Missing config, msg: {}", msg))]
93    MissingConfig {
94        msg: String,
95        #[snafu(implicit)]
96        location: Location,
97    },
98
99    #[snafu(display("Illegal config: {}", msg))]
100    IllegalConfig {
101        msg: String,
102        #[snafu(implicit)]
103        location: Location,
104    },
105
106    #[snafu(display("Failed to parse proxy options: {}", error))]
107    ParseProxyOpts {
108        #[snafu(source)]
109        error: reqwest::Error,
110        #[snafu(implicit)]
111        location: Location,
112    },
113
114    #[snafu(display("Failed to build reqwest client: {}", error))]
115    BuildClient {
116        #[snafu(implicit)]
117        location: Location,
118        #[snafu(source)]
119        error: reqwest::Error,
120    },
121
122    #[snafu(display("Failed to parse SQL: {}", sql))]
123    ParseSql {
124        sql: String,
125        #[snafu(implicit)]
126        location: Location,
127        source: query::error::Error,
128    },
129
130    #[snafu(display("Failed to plan statement"))]
131    PlanStatement {
132        #[snafu(implicit)]
133        location: Location,
134        source: query::error::Error,
135    },
136
137    #[snafu(display("Failed to load layered config"))]
138    LoadLayeredConfig {
139        #[snafu(source(from(common_config::error::Error, Box::new)))]
140        source: Box<common_config::error::Error>,
141        #[snafu(implicit)]
142        location: Location,
143    },
144
145    #[snafu(display("Failed to connect to Etcd at {etcd_addr}"))]
146    ConnectEtcd {
147        etcd_addr: String,
148        #[snafu(source)]
149        error: etcd_client::Error,
150        #[snafu(implicit)]
151        location: Location,
152    },
153
154    #[snafu(display("Failed to serde json"))]
155    SerdeJson {
156        #[snafu(source)]
157        error: serde_json::error::Error,
158        #[snafu(implicit)]
159        location: Location,
160    },
161
162    #[snafu(display("Failed to run http request: {reason}"))]
163    HttpQuerySql {
164        reason: String,
165        #[snafu(source)]
166        error: reqwest::Error,
167        #[snafu(implicit)]
168        location: Location,
169    },
170
171    #[snafu(display("Empty result from output"))]
172    EmptyResult {
173        #[snafu(implicit)]
174        location: Location,
175    },
176
177    #[snafu(display("Failed to manipulate file"))]
178    FileIo {
179        #[snafu(implicit)]
180        location: Location,
181        #[snafu(source)]
182        error: std::io::Error,
183    },
184
185    #[snafu(display("Failed to create directory {}", dir))]
186    CreateDir {
187        dir: String,
188        #[snafu(source)]
189        error: std::io::Error,
190    },
191
192    #[snafu(display("Failed to spawn thread"))]
193    SpawnThread {
194        #[snafu(source)]
195        error: std::io::Error,
196    },
197
198    #[snafu(display("Other error"))]
199    Other {
200        source: BoxedError,
201        #[snafu(implicit)]
202        location: Location,
203    },
204
205    #[snafu(display("Failed to build runtime"))]
206    BuildRuntime {
207        #[snafu(implicit)]
208        location: Location,
209        source: common_runtime::error::Error,
210    },
211
212    #[snafu(display("Failed to get cache from cache registry: {}", name))]
213    CacheRequired {
214        #[snafu(implicit)]
215        location: Location,
216        name: String,
217    },
218
219    #[snafu(display("Failed to build cache registry"))]
220    BuildCacheRegistry {
221        #[snafu(implicit)]
222        location: Location,
223        source: cache::error::Error,
224    },
225
226    #[snafu(display("Failed to initialize meta client"))]
227    MetaClientInit {
228        #[snafu(implicit)]
229        location: Location,
230        source: meta_client::error::Error,
231    },
232
233    #[snafu(display("Cannot find schema {schema} in catalog {catalog}"))]
234    SchemaNotFound {
235        catalog: String,
236        schema: String,
237        #[snafu(implicit)]
238        location: Location,
239    },
240
241    #[snafu(display("Table not found: {table_id}"))]
242    TableNotFound {
243        table_id: TableId,
244        #[snafu(implicit)]
245        location: Location,
246    },
247
248    #[snafu(display("OpenDAL operator failed"))]
249    OpenDal {
250        #[snafu(implicit)]
251        location: Location,
252        #[snafu(source)]
253        error: ObjectStoreError,
254    },
255
256    #[snafu(display("Output directory not set"))]
257    OutputDirNotSet {
258        #[snafu(implicit)]
259        location: Location,
260    },
261
262    #[snafu(display("Empty store addresses"))]
263    EmptyStoreAddrs {
264        #[snafu(implicit)]
265        location: Location,
266    },
267
268    #[snafu(display("Unsupported memory backend"))]
269    UnsupportedMemoryBackend {
270        #[snafu(implicit)]
271        location: Location,
272    },
273
274    #[snafu(display("File path invalid: {}", msg))]
275    InvalidFilePath {
276        msg: String,
277        #[snafu(implicit)]
278        location: Location,
279    },
280
281    #[snafu(display("Invalid arguments: {}", msg))]
282    InvalidArguments {
283        msg: String,
284        #[snafu(implicit)]
285        location: Location,
286    },
287
288    #[snafu(display("Failed to init backend"))]
289    InitBackend {
290        #[snafu(implicit)]
291        location: Location,
292        #[snafu(source)]
293        error: ObjectStoreError,
294    },
295
296    #[snafu(display("Covert column schemas to defs failed"))]
297    CovertColumnSchemasToDefs {
298        #[snafu(implicit)]
299        location: Location,
300        source: operator::error::Error,
301    },
302
303    #[snafu(display("Failed to send request to datanode: {}", peer))]
304    SendRequestToDatanode {
305        peer: Peer,
306        #[snafu(implicit)]
307        location: Location,
308        source: common_meta::error::Error,
309    },
310
311    #[snafu(display("Failed to get current directory"))]
312    GetCurrentDir {
313        #[snafu(implicit)]
314        location: Location,
315        #[snafu(source)]
316        error: std::io::Error,
317    },
318}
319
320pub type Result<T> = std::result::Result<T, Error>;
321
322impl ErrorExt for Error {
323    fn status_code(&self) -> StatusCode {
324        match self {
325            Error::InitMetadata { source, .. }
326            | Error::InitDdlManager { source, .. }
327            | Error::TableMetadata { source, .. } => source.status_code(),
328
329            Error::MissingConfig { .. }
330            | Error::LoadLayeredConfig { .. }
331            | Error::IllegalConfig { .. }
332            | Error::InitTimezone { .. }
333            | Error::ConnectEtcd { .. }
334            | Error::CreateDir { .. }
335            | Error::EmptyResult { .. }
336            | Error::InvalidFilePath { .. }
337            | Error::UnsupportedMemoryBackend { .. }
338            | Error::InvalidArguments { .. }
339            | Error::ParseProxyOpts { .. } => StatusCode::InvalidArguments,
340
341            Error::CovertColumnSchemasToDefs { source, .. } => source.status_code(),
342            Error::SendRequestToDatanode { source, .. } => source.status_code(),
343
344            Error::StartProcedureManager { source, .. }
345            | Error::StopProcedureManager { source, .. } => source.status_code(),
346            Error::StartWalOptionsAllocator { source, .. } => source.status_code(),
347            Error::HttpQuerySql { .. } => StatusCode::Internal,
348            Error::ParseSql { source, .. } | Error::PlanStatement { source, .. } => {
349                source.status_code()
350            }
351            Error::Unexpected { .. } => StatusCode::Unexpected,
352
353            Error::SerdeJson { .. }
354            | Error::FileIo { .. }
355            | Error::SpawnThread { .. }
356            | Error::InitTlsProvider { .. }
357            | Error::BuildClient { .. } => StatusCode::Unexpected,
358
359            Error::Other { source, .. } => source.status_code(),
360            Error::OpenDal { .. } | Error::InitBackend { .. } => StatusCode::Internal,
361            Error::OutputDirNotSet { .. } | Error::EmptyStoreAddrs { .. } => {
362                StatusCode::InvalidArguments
363            }
364
365            Error::BuildRuntime { source, .. } => source.status_code(),
366
367            Error::CacheRequired { .. }
368            | Error::BuildCacheRegistry { .. }
369            | Error::GetCurrentDir { .. } => StatusCode::Internal,
370            Error::MetaClientInit { source, .. } => source.status_code(),
371            Error::TableNotFound { .. } => StatusCode::TableNotFound,
372            Error::SchemaNotFound { .. } => StatusCode::DatabaseNotFound,
373        }
374    }
375
376    fn as_any(&self) -> &dyn Any {
377        self
378    }
379}