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::TimeUnit;
21use common_time::Timestamp;
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 expr in default constraint: {:?} for column: {}",
59        expr,
60        column_name
61    ))]
62    UnsupportedDefaultValue {
63        column_name: String,
64        expr: Expr,
65        #[snafu(implicit)]
66        location: Location,
67    },
68
69    #[snafu(display("Unable to convert sql value {} to datatype {:?}", value, datatype))]
70    ConvertSqlValue {
71        value: SqlValue,
72        datatype: ConcreteDataType,
73        #[snafu(implicit)]
74        location: Location,
75    },
76
77    #[snafu(display("Invalid sql value: {}", value))]
78    InvalidSqlValue {
79        value: String,
80        #[snafu(implicit)]
81        location: Location,
82    },
83
84    #[snafu(display("Unsupported unary operator {}", unary_op))]
85    UnsupportedUnaryOp {
86        unary_op: UnaryOperator,
87        #[snafu(implicit)]
88        location: Location,
89    },
90
91    #[snafu(display("Invalid unary operator {} for value {}", unary_op, value))]
92    InvalidUnaryOp {
93        unary_op: UnaryOperator,
94        value: Value,
95        #[snafu(implicit)]
96        location: Location,
97    },
98
99    #[snafu(display("Failed to cast SQL value {} to datatype {}", sql_value, datatype))]
100    InvalidCast {
101        sql_value: sqlparser::ast::Value,
102        datatype: ConcreteDataType,
103        #[snafu(implicit)]
104        location: Location,
105        source: datatypes::error::Error,
106    },
107
108    #[snafu(display("Unable to convert {} to datatype {:?}", value, datatype))]
109    ConvertStr {
110        value: String,
111        datatype: ConcreteDataType,
112        #[snafu(implicit)]
113        location: Location,
114    },
115
116    #[snafu(display(
117        "Converting timestamp {:?} to unit {:?} overflow",
118        timestamp,
119        target_unit
120    ))]
121    TimestampOverflow {
122        timestamp: Timestamp,
123        target_unit: TimeUnit,
124        #[snafu(implicit)]
125        location: Location,
126    },
127
128    #[snafu(display("Datatype error: {}", source))]
129    Datatype {
130        source: datatypes::error::Error,
131        #[snafu(implicit)]
132        location: Location,
133    },
134}
135
136impl ErrorExt for Error {
137    fn status_code(&self) -> StatusCode {
138        use Error::*;
139
140        match self {
141            UnsupportedDefaultValue { .. } => StatusCode::Unsupported,
142            ParseSqlValue { .. } => StatusCode::InvalidSyntax,
143            ColumnTypeMismatch { .. }
144            | InvalidSqlValue { .. }
145            | UnsupportedUnaryOp { .. }
146            | InvalidUnaryOp { .. }
147            | InvalidCast { .. }
148            | ConvertStr { .. }
149            | TimestampOverflow { .. } => StatusCode::InvalidArguments,
150            Datatype { source, .. } => source.status_code(),
151            ConvertSqlValue { .. } => StatusCode::Unsupported,
152        }
153    }
154
155    fn as_any(&self) -> &dyn Any {
156        self
157    }
158}