Skip to main content

query/
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;
16use std::time::{Duration, TryFromFloatSecsError};
17
18use common_error::ext::{BoxedError, ErrorExt};
19use common_error::status_code::StatusCode;
20use common_macro::stack_trace_debug;
21use common_query::error::datafusion_status_code;
22use datafusion::error::DataFusionError;
23use datatypes::prelude::ConcreteDataType;
24use datatypes::value::Value;
25use snafu::{Location, Snafu};
26use store_api::storage::RegionId;
27
28#[derive(Snafu)]
29#[snafu(visibility(pub))]
30#[stack_trace_debug]
31pub enum Error {
32    #[snafu(display("Unsupported expr type: {}", name))]
33    UnsupportedExpr {
34        name: String,
35        #[snafu(implicit)]
36        location: Location,
37    },
38
39    #[snafu(display("Unsupported show variable: {}", name))]
40    UnsupportedVariable {
41        name: String,
42        #[snafu(implicit)]
43        location: Location,
44    },
45
46    #[snafu(display("Operation {} not implemented yet", operation))]
47    Unimplemented {
48        operation: String,
49        #[snafu(implicit)]
50        location: Location,
51    },
52
53    #[snafu(display("General catalog error"))]
54    Catalog {
55        source: catalog::error::Error,
56        #[snafu(implicit)]
57        location: Location,
58    },
59
60    #[snafu(display("Partition rule manager error"))]
61    PartitionRuleManager {
62        source: partition::error::Error,
63        #[snafu(implicit)]
64        location: Location,
65    },
66
67    #[snafu(display("Table not found: {}", table))]
68    TableNotFound {
69        table: String,
70        #[snafu(implicit)]
71        location: Location,
72    },
73
74    #[snafu(display("Failed to create RecordBatch"))]
75    CreateRecordBatch {
76        source: common_recordbatch::error::Error,
77        #[snafu(implicit)]
78        location: Location,
79    },
80
81    #[snafu(display("Failure during query execution"))]
82    QueryExecution {
83        source: BoxedError,
84        #[snafu(implicit)]
85        location: Location,
86    },
87
88    #[snafu(display("Failure during query planning"))]
89    QueryPlan {
90        source: BoxedError,
91        #[snafu(implicit)]
92        location: Location,
93    },
94
95    #[snafu(display("Failure during query parsing, query: {}", query))]
96    QueryParse {
97        query: String,
98        source: BoxedError,
99        #[snafu(implicit)]
100        location: Location,
101    },
102
103    #[snafu(display("Illegal access to catalog: {} and schema: {}", catalog, schema))]
104    QueryAccessDenied {
105        catalog: String,
106        schema: String,
107        #[snafu(implicit)]
108        location: Location,
109    },
110
111    #[snafu(display("The SQL string has multiple statements, query: {}", query))]
112    MultipleStatements {
113        query: String,
114        #[snafu(implicit)]
115        location: Location,
116    },
117
118    #[snafu(display("Failed to parse timestamp `{}`", raw))]
119    ParseTimestamp {
120        raw: String,
121        #[snafu(source)]
122        error: chrono::ParseError,
123        #[snafu(implicit)]
124        location: Location,
125    },
126
127    #[snafu(display("Failed to parse float number `{}`", raw))]
128    ParseFloat {
129        raw: String,
130        #[snafu(source)]
131        error: std::num::ParseFloatError,
132        #[snafu(implicit)]
133        location: Location,
134    },
135
136    #[snafu(transparent)]
137    DataFusion {
138        #[snafu(source)]
139        error: DataFusionError,
140        #[snafu(implicit)]
141        location: Location,
142    },
143
144    #[snafu(display("General SQL error"))]
145    Sql {
146        #[snafu(implicit)]
147        location: Location,
148        source: sql::error::Error,
149    },
150
151    #[snafu(display("Failed to plan SQL"))]
152    PlanSql {
153        #[snafu(source)]
154        error: DataFusionError,
155        #[snafu(implicit)]
156        location: Location,
157    },
158
159    #[snafu(display("Timestamp column for table '{table_name}' is missing!"))]
160    MissingTimestampColumn {
161        table_name: String,
162        #[snafu(implicit)]
163        location: Location,
164    },
165
166    #[snafu(display("Failed to convert value to sql value: {}", value))]
167    ConvertSqlValue {
168        value: Value,
169        source: sql::error::Error,
170        #[snafu(implicit)]
171        location: Location,
172    },
173
174    #[snafu(display("Failed to convert concrete type to sql type: {:?}", datatype))]
175    ConvertSqlType {
176        datatype: ConcreteDataType,
177        source: sql::error::Error,
178        #[snafu(implicit)]
179        location: Location,
180    },
181
182    #[snafu(display("Missing required field: {}", name))]
183    MissingRequiredField {
184        name: String,
185        #[snafu(implicit)]
186        location: Location,
187    },
188
189    #[snafu(display("Failed to regex"))]
190    BuildRegex {
191        #[snafu(implicit)]
192        location: Location,
193        #[snafu(source)]
194        error: regex::Error,
195    },
196
197    #[snafu(display("Failed to build data source backend"))]
198    BuildBackend {
199        source: common_datasource::error::Error,
200        #[snafu(implicit)]
201        location: Location,
202    },
203
204    #[snafu(display("Failed to list objects"))]
205    ListObjects {
206        source: common_datasource::error::Error,
207        #[snafu(implicit)]
208        location: Location,
209    },
210
211    #[snafu(display("Failed to parse file format"))]
212    ParseFileFormat {
213        source: common_datasource::error::Error,
214        #[snafu(implicit)]
215        location: Location,
216    },
217
218    #[snafu(display("Failed to infer schema"))]
219    InferSchema {
220        source: common_datasource::error::Error,
221        #[snafu(implicit)]
222        location: Location,
223    },
224
225    #[snafu(display("Failed to convert datafusion schema"))]
226    ConvertSchema {
227        source: datatypes::error::Error,
228        #[snafu(implicit)]
229        location: Location,
230    },
231
232    #[snafu(display("Unknown table type, downcast failed"))]
233    UnknownTable {
234        #[snafu(implicit)]
235        location: Location,
236    },
237
238    #[snafu(display("Cannot find time index column in table {}", table))]
239    TimeIndexNotFound {
240        table: String,
241        #[snafu(implicit)]
242        location: Location,
243    },
244
245    #[snafu(display("Failed to add duration '{:?}' to SystemTime, overflowed", duration))]
246    AddSystemTimeOverflow {
247        duration: Duration,
248        #[snafu(implicit)]
249        location: Location,
250    },
251
252    #[snafu(display(
253        "Column schema incompatible, column: {}, file_type: {}, table_type: {}",
254        column,
255        file_type,
256        table_type
257    ))]
258    ColumnSchemaIncompatible {
259        column: String,
260        file_type: ConcreteDataType,
261        table_type: ConcreteDataType,
262        #[snafu(implicit)]
263        location: Location,
264    },
265
266    #[snafu(display("Column schema has no default value, column: {}", column))]
267    ColumnSchemaNoDefault {
268        column: String,
269        #[snafu(implicit)]
270        location: Location,
271    },
272
273    #[snafu(display("Region query error"))]
274    RegionQuery {
275        source: BoxedError,
276        #[snafu(implicit)]
277        location: Location,
278    },
279
280    #[snafu(display("Table mutation error"))]
281    TableMutation {
282        source: common_query::error::Error,
283        #[snafu(implicit)]
284        location: Location,
285    },
286
287    #[snafu(display("Missing table mutation handler"))]
288    MissingTableMutationHandler {
289        #[snafu(implicit)]
290        location: Location,
291    },
292
293    #[snafu(display("Range Query: {}", msg))]
294    RangeQuery {
295        msg: String,
296        #[snafu(implicit)]
297        location: Location,
298    },
299
300    #[snafu(display(
301        "Failed to get metadata from engine {} for region_id {}",
302        engine,
303        region_id,
304    ))]
305    GetRegionMetadata {
306        engine: String,
307        region_id: RegionId,
308        #[snafu(implicit)]
309        location: Location,
310        source: BoxedError,
311    },
312
313    #[snafu(display("Cannot change read-only table: {}", table))]
314    TableReadOnly {
315        table: String,
316        #[snafu(implicit)]
317        location: Location,
318    },
319
320    #[snafu(display("Failed to get fulltext options"))]
321    GetFulltextOptions {
322        source: datatypes::error::Error,
323        #[snafu(implicit)]
324        location: Location,
325    },
326
327    #[snafu(display("Failed to get SKIPPING index options"))]
328    GetSkippingIndexOptions {
329        source: datatypes::error::Error,
330        #[snafu(implicit)]
331        location: Location,
332    },
333
334    #[snafu(display("Failed to get VECTOR index options"))]
335    GetVectorIndexOptions {
336        source: datatypes::error::Error,
337        #[snafu(implicit)]
338        location: Location,
339    },
340
341    #[snafu(display(
342        "Column schema mismatch in CTE {}, original: {:?}, expected: {:?}",
343        cte_name,
344        original,
345        expected,
346    ))]
347    CteColumnSchemaMismatch {
348        cte_name: String,
349        original: Vec<String>,
350        expected: Vec<String>,
351        #[snafu(implicit)]
352        location: Location,
353    },
354
355    #[snafu(display("Failed to convert value for region pruning"))]
356    ConvertValue {
357        source: datatypes::error::Error,
358        #[snafu(implicit)]
359        location: Location,
360    },
361
362    #[snafu(display("Failed to convert float seconds to duration, raw: {}", raw))]
363    TryIntoDuration {
364        raw: String,
365        #[snafu(source)]
366        error: TryFromFloatSecsError,
367        #[snafu(implicit)]
368        location: Location,
369    },
370
371    #[snafu(display("Invalid query context extension: {}", reason))]
372    InvalidQueryContextExtension {
373        reason: String,
374        #[snafu(implicit)]
375        location: Location,
376    },
377
378    #[snafu(display(
379        "Conflicting snapshot sequence observed for region {} in a single query (existing={}, new={})",
380        region_id,
381        existing,
382        new
383    ))]
384    ConflictingSnapshotSequence {
385        region_id: RegionId,
386        existing: u64,
387        new: u64,
388        #[snafu(implicit)]
389        location: Location,
390    },
391
392    #[snafu(transparent)]
393    Datatypes {
394        source: datatypes::error::Error,
395        #[snafu(implicit)]
396        location: Location,
397    },
398}
399
400impl ErrorExt for Error {
401    fn status_code(&self) -> StatusCode {
402        use Error::*;
403
404        match self {
405            QueryParse { .. } | MultipleStatements { .. } | RangeQuery { .. } => {
406                StatusCode::InvalidSyntax
407            }
408            UnsupportedExpr { .. }
409            | Unimplemented { .. }
410            | UnknownTable { .. }
411            | TimeIndexNotFound { .. }
412            | ParseTimestamp { .. }
413            | ParseFloat { .. }
414            | MissingRequiredField { .. }
415            | BuildRegex { .. }
416            | ConvertSchema { .. }
417            | AddSystemTimeOverflow { .. }
418            | ColumnSchemaIncompatible { .. }
419            | UnsupportedVariable { .. }
420            | ColumnSchemaNoDefault { .. }
421            | CteColumnSchemaMismatch { .. }
422            | ConvertValue { .. }
423            | TryIntoDuration { .. }
424            | InvalidQueryContextExtension { .. }
425            | ConflictingSnapshotSequence { .. } => StatusCode::InvalidArguments,
426
427            BuildBackend { .. } | ListObjects { .. } => StatusCode::StorageUnavailable,
428
429            TableNotFound { .. } => StatusCode::TableNotFound,
430
431            ParseFileFormat { source, .. } | InferSchema { source, .. } => source.status_code(),
432
433            QueryAccessDenied { .. } => StatusCode::AccessDenied,
434            Catalog { source, .. } => source.status_code(),
435            CreateRecordBatch { source, .. } => source.status_code(),
436            PartitionRuleManager { source, .. } => source.status_code(),
437            QueryExecution { source, .. } | QueryPlan { source, .. } => source.status_code(),
438            PlanSql { error, .. } => {
439                datafusion_status_code::<Self>(error, Some(StatusCode::PlanQuery))
440            }
441
442            DataFusion { error, .. } => datafusion_status_code::<Self>(error, None),
443
444            MissingTimestampColumn { .. } => StatusCode::EngineExecuteQuery,
445            Sql { source, .. } => source.status_code(),
446
447            ConvertSqlType { source, .. } | ConvertSqlValue { source, .. } => source.status_code(),
448
449            RegionQuery { source, .. } => source.status_code(),
450            TableMutation { source, .. } => source.status_code(),
451            MissingTableMutationHandler { .. } => StatusCode::Unexpected,
452            GetRegionMetadata { .. } => StatusCode::RegionNotReady,
453            TableReadOnly { .. } => StatusCode::Unsupported,
454
455            GetFulltextOptions { source, .. }
456            | GetSkippingIndexOptions { source, .. }
457            | GetVectorIndexOptions { source, .. }
458            | Datatypes { source, .. } => source.status_code(),
459        }
460    }
461
462    fn as_any(&self) -> &dyn Any {
463        self
464    }
465}
466
467pub type Result<T> = std::result::Result<T, Error>;
468
469impl From<Error> for DataFusionError {
470    fn from(e: Error) -> DataFusionError {
471        DataFusionError::External(Box::new(e))
472    }
473}