Skip to main content

cli/data/export_v2/
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 snafu::{Location, Snafu};
21
22#[derive(Snafu)]
23#[snafu(visibility(pub))]
24#[stack_trace_debug]
25pub enum Error {
26    #[snafu(display("Invalid URI '{}': {}", uri, reason))]
27    InvalidUri {
28        uri: String,
29        reason: String,
30        #[snafu(implicit)]
31        location: Location,
32    },
33
34    #[snafu(display("Unsupported storage scheme: {}", scheme))]
35    UnsupportedScheme {
36        scheme: String,
37        #[snafu(implicit)]
38        location: Location,
39    },
40
41    #[snafu(display("Storage operation '{}' failed", operation))]
42    StorageOperation {
43        operation: String,
44        #[snafu(source)]
45        error: object_store::Error,
46        #[snafu(implicit)]
47        location: Location,
48    },
49
50    #[snafu(display("Failed to parse manifest"))]
51    ManifestParse {
52        #[snafu(source)]
53        error: serde_json::Error,
54        #[snafu(implicit)]
55        location: Location,
56    },
57
58    #[snafu(display("Failed to serialize manifest"))]
59    ManifestSerialize {
60        #[snafu(source)]
61        error: serde_json::Error,
62        #[snafu(implicit)]
63        location: Location,
64    },
65
66    #[snafu(display("Failed to decode text file as UTF-8"))]
67    TextDecode {
68        #[snafu(source)]
69        error: std::string::FromUtf8Error,
70        #[snafu(implicit)]
71        location: Location,
72    },
73
74    #[snafu(display("I/O error while {}: {}", operation, error))]
75    Io {
76        operation: &'static str,
77        error: std::io::Error,
78        #[snafu(implicit)]
79        location: Location,
80    },
81
82    #[snafu(display(
83        "Cannot resume snapshot with a different schema_only mode (existing: {}, requested: {}). Use --force to recreate.",
84        existing_schema_only,
85        requested_schema_only
86    ))]
87    SchemaOnlyModeMismatch {
88        existing_schema_only: bool,
89        requested_schema_only: bool,
90        #[snafu(implicit)]
91        location: Location,
92    },
93
94    #[snafu(display(
95        "Cannot resume snapshot with different {} (existing: {}, requested: {}). Use --force to recreate.",
96        field,
97        existing,
98        requested
99    ))]
100    ResumeConfigMismatch {
101        field: String,
102        existing: String,
103        requested: String,
104        #[snafu(implicit)]
105        location: Location,
106    },
107
108    #[snafu(display("Failed to parse time: invalid format: {}", input))]
109    TimeParseInvalidFormat {
110        input: String,
111        #[snafu(implicit)]
112        location: Location,
113    },
114
115    #[snafu(display("Failed to parse time: end_time is before start_time"))]
116    TimeParseEndBeforeStart {
117        #[snafu(implicit)]
118        location: Location,
119    },
120
121    #[snafu(display(
122        "chunk_time_window requires both --start-time and --end-time to be specified"
123    ))]
124    ChunkTimeWindowRequiresBounds {
125        #[snafu(implicit)]
126        location: Location,
127    },
128
129    #[snafu(display("--schema-only cannot be used with data export arguments: {}", args))]
130    SchemaOnlyArgsNotAllowed {
131        args: String,
132        #[snafu(implicit)]
133        location: Location,
134    },
135
136    #[snafu(display("Empty result from query"))]
137    EmptyResult {
138        #[snafu(implicit)]
139        location: Location,
140    },
141
142    #[snafu(display("Unexpected value type in query result"))]
143    UnexpectedValueType {
144        #[snafu(implicit)]
145        location: Location,
146    },
147
148    #[snafu(display("Database error"))]
149    Database {
150        #[snafu(source)]
151        error: crate::error::Error,
152        #[snafu(implicit)]
153        location: Location,
154    },
155
156    #[snafu(display("Snapshot not found at '{}'", uri))]
157    SnapshotNotFound {
158        uri: String,
159        #[snafu(implicit)]
160        location: Location,
161    },
162
163    #[snafu(display("Schema '{}' not found in catalog '{}'", schema, catalog))]
164    SchemaNotFound {
165        catalog: String,
166        schema: String,
167        #[snafu(implicit)]
168        location: Location,
169    },
170
171    #[snafu(display("Failed to parse URL"))]
172    UrlParse {
173        #[snafu(source)]
174        error: url::ParseError,
175        #[snafu(implicit)]
176        location: Location,
177    },
178
179    #[snafu(display("Failed to build object store"))]
180    BuildObjectStore {
181        #[snafu(source)]
182        error: object_store::Error,
183        #[snafu(implicit)]
184        location: Location,
185    },
186
187    #[snafu(display("Manifest version mismatch: expected {}, found {}", expected, found))]
188    ManifestVersionMismatch {
189        expected: u32,
190        found: u32,
191        #[snafu(implicit)]
192        location: Location,
193    },
194
195    #[snafu(display(
196        "Snapshot verification failed: {} error(s), {} warning(s)",
197        errors,
198        warnings
199    ))]
200    SnapshotVerifyFailed {
201        errors: usize,
202        warnings: usize,
203        #[snafu(implicit)]
204        location: Location,
205    },
206}
207
208pub type Result<T> = std::result::Result<T, Error>;
209
210impl ErrorExt for Error {
211    fn status_code(&self) -> StatusCode {
212        match self {
213            Error::InvalidUri { .. }
214            | Error::UnsupportedScheme { .. }
215            | Error::SchemaOnlyModeMismatch { .. }
216            | Error::ResumeConfigMismatch { .. }
217            | Error::ManifestVersionMismatch { .. }
218            | Error::SchemaOnlyArgsNotAllowed { .. }
219            | Error::SnapshotVerifyFailed { .. } => StatusCode::InvalidArguments,
220            Error::TimeParseInvalidFormat { .. }
221            | Error::TimeParseEndBeforeStart { .. }
222            | Error::ChunkTimeWindowRequiresBounds { .. } => StatusCode::InvalidArguments,
223
224            Error::StorageOperation { .. }
225            | Error::ManifestParse { .. }
226            | Error::ManifestSerialize { .. }
227            | Error::TextDecode { .. }
228            | Error::BuildObjectStore { .. } => StatusCode::StorageUnavailable,
229
230            Error::EmptyResult { .. }
231            | Error::UnexpectedValueType { .. }
232            | Error::UrlParse { .. } => StatusCode::Internal,
233
234            Error::Io { .. } => StatusCode::External,
235
236            Error::Database { error, .. } => error.status_code(),
237
238            Error::SnapshotNotFound { .. } => StatusCode::InvalidArguments,
239            Error::SchemaNotFound { .. } => StatusCode::DatabaseNotFound,
240        }
241    }
242
243    fn as_any(&self) -> &dyn Any {
244        self
245    }
246}