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_common::DataFusionError;
23use datafusion_sql::sqlparser::ast::UnaryOperator;
24use datatypes::prelude::{ConcreteDataType, Value};
25use snafu::{Location, Snafu};
26use sqlparser::ast::Ident;
27use sqlparser::parser::ParserError;
28
29use crate::ast::{Expr, Value as SqlValue};
30use crate::parsers::error::TQLError;
31
32pub type Result<T> = std::result::Result<T, Error>;
33
34/// SQL parser errors.
35// Now the error in parser does not contain backtrace to avoid generating backtrace
36// every time the parser parses an invalid SQL.
37#[derive(Snafu)]
38#[snafu(visibility(pub))]
39#[stack_trace_debug]
40pub enum Error {
41    #[snafu(display("SQL statement is not supported, keyword: {}", keyword))]
42    Unsupported {
43        keyword: String,
44        #[snafu(implicit)]
45        location: Location,
46    },
47
48    #[snafu(display(
49        "Unexpected token while parsing SQL statement, expected: '{}', found: {}",
50        expected,
51        actual,
52    ))]
53    Unexpected {
54        expected: String,
55        actual: String,
56        #[snafu(source)]
57        error: ParserError,
58        #[snafu(implicit)]
59        location: Location,
60    },
61
62    #[snafu(display(
63        "Unsupported expr in default constraint: {:?} for column: {}",
64        expr,
65        column_name
66    ))]
67    UnsupportedDefaultValue {
68        column_name: String,
69        expr: Expr,
70        #[snafu(implicit)]
71        location: Location,
72    },
73
74    // Syntax error from sql parser.
75    #[snafu(display("Invalid SQL syntax"))]
76    Syntax {
77        #[snafu(source)]
78        error: ParserError,
79        #[snafu(implicit)]
80        location: Location,
81    },
82
83    // Syntax error from tql parser.
84    #[snafu(display("Invalid TQL syntax"))]
85    TQLSyntax {
86        #[snafu(source)]
87        error: TQLError,
88        #[snafu(implicit)]
89        location: Location,
90    },
91
92    #[snafu(display("Missing time index constraint"))]
93    MissingTimeIndex {},
94
95    #[snafu(display("Invalid time index: {}", msg))]
96    InvalidTimeIndex {
97        msg: String,
98        #[snafu(implicit)]
99        location: Location,
100    },
101
102    #[snafu(display("Invalid SQL, error: {}", msg))]
103    InvalidSql {
104        msg: String,
105        #[snafu(implicit)]
106        location: Location,
107    },
108
109    #[snafu(display(
110        "Unexpected token while parsing SQL statement, expected: '{}', found: {}",
111        expected,
112        actual,
113    ))]
114    UnexpectedToken {
115        expected: String,
116        actual: String,
117        #[snafu(implicit)]
118        location: Location,
119    },
120
121    #[snafu(display("Invalid column option, column name: {}, error: {}", name, msg))]
122    InvalidColumnOption {
123        name: String,
124        msg: String,
125        #[snafu(implicit)]
126        location: Location,
127    },
128
129    #[snafu(display("SQL data type not supported yet: {:?}", t))]
130    SqlTypeNotSupported {
131        t: crate::ast::DataType,
132        #[snafu(implicit)]
133        location: Location,
134    },
135    #[snafu(display("ConcreteDataType not supported yet: {:?}", t))]
136    ConcreteTypeNotSupported {
137        t: ConcreteDataType,
138        #[snafu(implicit)]
139        location: Location,
140    },
141
142    #[snafu(display("Failed to parse value: {}", msg))]
143    ParseSqlValue {
144        msg: String,
145        #[snafu(implicit)]
146        location: Location,
147    },
148
149    #[snafu(display(
150        "Column {} expect type: {:?}, actual: {:?}",
151        column_name,
152        expect,
153        actual,
154    ))]
155    ColumnTypeMismatch {
156        column_name: String,
157        expect: ConcreteDataType,
158        actual: ConcreteDataType,
159        #[snafu(implicit)]
160        location: Location,
161    },
162
163    #[snafu(display("Invalid database name: {}", name))]
164    InvalidDatabaseName {
165        name: String,
166        #[snafu(implicit)]
167        location: Location,
168    },
169
170    #[snafu(display("Invalid interval provided: {}", reason))]
171    InvalidInterval {
172        reason: String,
173        #[snafu(implicit)]
174        location: Location,
175    },
176
177    #[snafu(display("Unrecognized database option key: {}", key))]
178    InvalidDatabaseOption {
179        key: String,
180        #[snafu(implicit)]
181        location: Location,
182    },
183
184    #[snafu(display("Invalid table name: {}", name))]
185    InvalidTableName {
186        name: String,
187        #[snafu(implicit)]
188        location: Location,
189    },
190
191    #[snafu(display("Invalid flow name: {}", name))]
192    InvalidFlowName {
193        name: String,
194        #[snafu(implicit)]
195        location: Location,
196    },
197
198    #[snafu(display("Invalid default constraint, column: {}", column))]
199    InvalidDefault {
200        column: String,
201        #[snafu(implicit)]
202        location: Location,
203        source: datatypes::error::Error,
204    },
205
206    #[snafu(display("Failed to cast SQL value {} to datatype {}", sql_value, datatype))]
207    InvalidCast {
208        sql_value: sqlparser::ast::Value,
209        datatype: ConcreteDataType,
210        #[snafu(implicit)]
211        location: Location,
212        source: datatypes::error::Error,
213    },
214
215    #[snafu(display("Invalid unary operator {} for value {}", unary_op, value))]
216    InvalidUnaryOp {
217        unary_op: UnaryOperator,
218        value: Value,
219        #[snafu(implicit)]
220        location: Location,
221    },
222
223    #[snafu(display("Unsupported unary operator {}", unary_op))]
224    UnsupportedUnaryOp {
225        unary_op: UnaryOperator,
226        #[snafu(implicit)]
227        location: Location,
228    },
229
230    #[snafu(display("Unrecognized table option key: {}", key))]
231    InvalidTableOption {
232        key: String,
233        #[snafu(implicit)]
234        location: Location,
235    },
236
237    #[snafu(display("Unrecognized table option key: {}, value: {}", key, value))]
238    InvalidTableOptionValue {
239        key: Ident,
240        value: Expr,
241        #[snafu(implicit)]
242        location: Location,
243    },
244
245    #[snafu(display("Failed to serialize column default constraint"))]
246    SerializeColumnDefaultConstraint {
247        #[snafu(implicit)]
248        location: Location,
249        source: datatypes::error::Error,
250    },
251
252    #[snafu(display("Failed to convert data type to gRPC data type defined in proto"))]
253    ConvertToGrpcDataType {
254        #[snafu(implicit)]
255        location: Location,
256        source: api::error::Error,
257    },
258
259    #[snafu(display("Invalid sql value: {}", value))]
260    InvalidSqlValue {
261        value: String,
262        #[snafu(implicit)]
263        location: Location,
264    },
265
266    #[snafu(display(
267        "Converting timestamp {:?} to unit {:?} overflow",
268        timestamp,
269        target_unit
270    ))]
271    TimestampOverflow {
272        timestamp: Timestamp,
273        target_unit: TimeUnit,
274        #[snafu(implicit)]
275        location: Location,
276    },
277
278    #[snafu(display("Unable to convert statement {} to DataFusion statement", statement))]
279    ConvertToDfStatement {
280        statement: String,
281        #[snafu(implicit)]
282        location: Location,
283    },
284
285    #[snafu(display("Unable to convert sql value {} to datatype {:?}", value, datatype))]
286    ConvertSqlValue {
287        value: SqlValue,
288        datatype: ConcreteDataType,
289        #[snafu(implicit)]
290        location: Location,
291    },
292
293    #[snafu(display("Unable to convert value {} to sql value", value))]
294    ConvertValue {
295        value: Value,
296        #[snafu(implicit)]
297        location: Location,
298    },
299
300    #[snafu(display("Failed to convert to logical TQL expression"))]
301    ConvertToLogicalExpression {
302        #[snafu(source)]
303        error: DataFusionError,
304        #[snafu(implicit)]
305        location: Location,
306    },
307
308    #[snafu(display("Failed to simplify TQL expression"))]
309    Simplification {
310        #[snafu(source)]
311        error: DataFusionError,
312        #[snafu(implicit)]
313        location: Location,
314    },
315
316    #[snafu(display(
317        "Permission denied while operating catalog {} from current catalog {}",
318        target,
319        current
320    ))]
321    PermissionDenied {
322        target: String,
323        current: String,
324        #[snafu(implicit)]
325        location: Location,
326    },
327
328    #[snafu(display("Failed to set fulltext option"))]
329    SetFulltextOption {
330        source: datatypes::error::Error,
331        #[snafu(implicit)]
332        location: Location,
333    },
334
335    #[snafu(display("Failed to set SKIPPING index option"))]
336    SetSkippingIndexOption {
337        source: datatypes::error::Error,
338        #[snafu(implicit)]
339        location: Location,
340    },
341
342    #[snafu(display("Datatype error: {}", source))]
343    Datatype {
344        source: datatypes::error::Error,
345        #[snafu(implicit)]
346        location: Location,
347    },
348
349    #[snafu(display(
350        "Invalid partition number: {}, should be in range [2, 65536]",
351        partition_num
352    ))]
353    InvalidPartitionNumber {
354        partition_num: u32,
355        #[snafu(implicit)]
356        location: Location,
357    },
358
359    #[snafu(display("Unable to convert {} to datatype {:?}", value, datatype))]
360    ConvertStr {
361        value: String,
362        datatype: ConcreteDataType,
363        #[snafu(implicit)]
364        location: Location,
365    },
366}
367
368impl ErrorExt for Error {
369    fn status_code(&self) -> StatusCode {
370        use Error::*;
371
372        match self {
373            UnsupportedDefaultValue { .. } | Unsupported { .. } => StatusCode::Unsupported,
374            Unexpected { .. }
375            | Syntax { .. }
376            | TQLSyntax { .. }
377            | MissingTimeIndex { .. }
378            | InvalidTimeIndex { .. }
379            | InvalidSql { .. }
380            | ParseSqlValue { .. }
381            | SqlTypeNotSupported { .. }
382            | ConcreteTypeNotSupported { .. }
383            | UnexpectedToken { .. }
384            | InvalidDefault { .. } => StatusCode::InvalidSyntax,
385
386            InvalidColumnOption { .. }
387            | InvalidTableOptionValue { .. }
388            | InvalidDatabaseName { .. }
389            | InvalidDatabaseOption { .. }
390            | ColumnTypeMismatch { .. }
391            | InvalidTableName { .. }
392            | InvalidFlowName { .. }
393            | InvalidSqlValue { .. }
394            | TimestampOverflow { .. }
395            | InvalidTableOption { .. }
396            | InvalidCast { .. }
397            | ConvertToLogicalExpression { .. }
398            | Simplification { .. }
399            | InvalidInterval { .. }
400            | InvalidUnaryOp { .. }
401            | InvalidPartitionNumber { .. }
402            | UnsupportedUnaryOp { .. }
403            | ConvertStr { .. } => StatusCode::InvalidArguments,
404
405            SerializeColumnDefaultConstraint { source, .. } => source.status_code(),
406            ConvertToGrpcDataType { source, .. } => source.status_code(),
407            Datatype { source, .. } => source.status_code(),
408            ConvertToDfStatement { .. } => StatusCode::Internal,
409            ConvertSqlValue { .. } | ConvertValue { .. } => StatusCode::Unsupported,
410
411            PermissionDenied { .. } => StatusCode::PermissionDenied,
412            SetFulltextOption { .. } | SetSkippingIndexOption { .. } => StatusCode::Unexpected,
413        }
414    }
415
416    fn as_any(&self) -> &dyn Any {
417        self
418    }
419}