common_sql/
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 common_time::Timestamp;
21use common_time::timestamp::TimeUnit;
22use datafusion_sql::sqlparser::ast::UnaryOperator;
23use datatypes::prelude::{ConcreteDataType, Value};
24use snafu::{Location, Snafu};
25pub use sqlparser::ast::{Expr, Value as SqlValue};
26
27pub type Result<T> = std::result::Result<T, Error>;
28
29/// SQL parser errors.
30// Now the error in parser does not contain backtrace to avoid generating backtrace
31// every time the parser parses an invalid SQL.
32#[derive(Snafu)]
33#[snafu(visibility(pub))]
34#[stack_trace_debug]
35pub enum Error {
36    #[snafu(display(
37        "Column {} expect type: {:?}, actual: {:?}",
38        column_name,
39        expect,
40        actual,
41    ))]
42    ColumnTypeMismatch {
43        column_name: String,
44        expect: ConcreteDataType,
45        actual: ConcreteDataType,
46        #[snafu(implicit)]
47        location: Location,
48    },
49
50    #[snafu(display("Failed to parse value: {}", msg))]
51    ParseSqlValue {
52        msg: String,
53        #[snafu(implicit)]
54        location: Location,
55    },
56
57    #[snafu(display(
58        "Unsupported default constraint for column: '{column_name}', reason: {reason}"
59    ))]
60    UnsupportedDefaultValue {
61        column_name: String,
62        reason: String,
63        #[snafu(implicit)]
64        location: Location,
65    },
66
67    #[snafu(display("Unable to convert sql value {} to datatype {:?}", value, datatype))]
68    ConvertSqlValue {
69        value: SqlValue,
70        datatype: ConcreteDataType,
71        #[snafu(implicit)]
72        location: Location,
73    },
74
75    #[snafu(display("Invalid sql value: {}", value))]
76    InvalidSqlValue {
77        value: String,
78        #[snafu(implicit)]
79        location: Location,
80    },
81
82    #[snafu(display("Unsupported unary operator {}", unary_op))]
83    UnsupportedUnaryOp {
84        unary_op: UnaryOperator,
85        #[snafu(implicit)]
86        location: Location,
87    },
88
89    #[snafu(display("Invalid unary operator {} for value {}", unary_op, value))]
90    InvalidUnaryOp {
91        unary_op: UnaryOperator,
92        value: Value,
93        #[snafu(implicit)]
94        location: Location,
95    },
96
97    #[snafu(display("Failed to cast SQL value {} to datatype {}", sql_value, datatype))]
98    InvalidCast {
99        sql_value: sqlparser::ast::Value,
100        datatype: ConcreteDataType,
101        #[snafu(implicit)]
102        location: Location,
103        source: datatypes::error::Error,
104    },
105
106    #[snafu(display("Unable to convert {} to datatype {:?}", value, datatype))]
107    ConvertStr {
108        value: String,
109        datatype: ConcreteDataType,
110        #[snafu(implicit)]
111        location: Location,
112    },
113
114    #[snafu(display(
115        "Converting timestamp {:?} to unit {:?} overflow",
116        timestamp,
117        target_unit
118    ))]
119    TimestampOverflow {
120        timestamp: Timestamp,
121        target_unit: TimeUnit,
122        #[snafu(implicit)]
123        location: Location,
124    },
125
126    #[snafu(display("Datatype error: {}", source))]
127    Datatype {
128        source: datatypes::error::Error,
129        #[snafu(implicit)]
130        location: Location,
131    },
132
133    #[snafu(display("Failed to deserialize data, json: {}", json))]
134    Deserialize {
135        #[snafu(source)]
136        error: serde_json::Error,
137        #[snafu(implicit)]
138        location: Location,
139        json: String,
140    },
141}
142
143impl ErrorExt for Error {
144    fn status_code(&self) -> StatusCode {
145        use Error::*;
146
147        match self {
148            UnsupportedDefaultValue { .. } => StatusCode::Unsupported,
149            ParseSqlValue { .. } => StatusCode::InvalidSyntax,
150            ColumnTypeMismatch { .. }
151            | InvalidSqlValue { .. }
152            | UnsupportedUnaryOp { .. }
153            | InvalidUnaryOp { .. }
154            | InvalidCast { .. }
155            | ConvertStr { .. }
156            | TimestampOverflow { .. } => StatusCode::InvalidArguments,
157            Deserialize { .. } => StatusCode::Unexpected,
158
159            Datatype { source, .. } => source.status_code(),
160            ConvertSqlValue { .. } => StatusCode::Unsupported,
161        }
162    }
163
164    fn as_any(&self) -> &dyn Any {
165        self
166    }
167}