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 flow query: {}", reason))]
199    InvalidFlowQuery {
200        reason: String,
201        #[snafu(implicit)]
202        location: Location,
203    },
204
205    #[snafu(display("Invalid default constraint, column: {}", column))]
206    InvalidDefault {
207        column: String,
208        #[snafu(implicit)]
209        location: Location,
210        source: datatypes::error::Error,
211    },
212
213    #[snafu(display("Failed to cast SQL value {} to datatype {}", sql_value, datatype))]
214    InvalidCast {
215        sql_value: sqlparser::ast::Value,
216        datatype: ConcreteDataType,
217        #[snafu(implicit)]
218        location: Location,
219        source: datatypes::error::Error,
220    },
221
222    #[snafu(display("Invalid unary operator {} for value {}", unary_op, value))]
223    InvalidUnaryOp {
224        unary_op: UnaryOperator,
225        value: Value,
226        #[snafu(implicit)]
227        location: Location,
228    },
229
230    #[snafu(display("Unsupported unary operator {}", unary_op))]
231    UnsupportedUnaryOp {
232        unary_op: UnaryOperator,
233        #[snafu(implicit)]
234        location: Location,
235    },
236
237    #[snafu(display("Unrecognized table option key: {}", key))]
238    InvalidTableOption {
239        key: String,
240        #[snafu(implicit)]
241        location: Location,
242    },
243
244    #[snafu(display("Unrecognized table option key: {}, value: {}", key, value))]
245    InvalidTableOptionValue {
246        key: Ident,
247        value: Expr,
248        #[snafu(implicit)]
249        location: Location,
250    },
251
252    #[snafu(display("Failed to serialize column default constraint"))]
253    SerializeColumnDefaultConstraint {
254        #[snafu(implicit)]
255        location: Location,
256        source: datatypes::error::Error,
257    },
258
259    #[snafu(display("Failed to convert data type to gRPC data type defined in proto"))]
260    ConvertToGrpcDataType {
261        #[snafu(implicit)]
262        location: Location,
263        source: api::error::Error,
264    },
265
266    #[snafu(display("Invalid sql value: {}", value))]
267    InvalidSqlValue {
268        value: String,
269        #[snafu(implicit)]
270        location: Location,
271    },
272
273    #[snafu(display(
274        "Converting timestamp {:?} to unit {:?} overflow",
275        timestamp,
276        target_unit
277    ))]
278    TimestampOverflow {
279        timestamp: Timestamp,
280        target_unit: TimeUnit,
281        #[snafu(implicit)]
282        location: Location,
283    },
284
285    #[snafu(display("Unable to convert statement {} to DataFusion statement", statement))]
286    ConvertToDfStatement {
287        statement: String,
288        #[snafu(implicit)]
289        location: Location,
290    },
291
292    #[snafu(display("Unable to convert sql value {} to datatype {:?}", value, datatype))]
293    ConvertSqlValue {
294        value: SqlValue,
295        datatype: ConcreteDataType,
296        #[snafu(implicit)]
297        location: Location,
298    },
299
300    #[snafu(display("Unable to convert value {} to sql value", value))]
301    ConvertValue {
302        value: Value,
303        #[snafu(implicit)]
304        location: Location,
305    },
306
307    #[snafu(display("Failed to convert to logical TQL expression"))]
308    ConvertToLogicalExpression {
309        #[snafu(source)]
310        error: DataFusionError,
311        #[snafu(implicit)]
312        location: Location,
313    },
314
315    #[snafu(display("Failed to simplify TQL expression"))]
316    Simplification {
317        #[snafu(source)]
318        error: DataFusionError,
319        #[snafu(implicit)]
320        location: Location,
321    },
322
323    #[snafu(display(
324        "Permission denied while operating catalog {} from current catalog {}",
325        target,
326        current
327    ))]
328    PermissionDenied {
329        target: String,
330        current: String,
331        #[snafu(implicit)]
332        location: Location,
333    },
334
335    #[snafu(display("Failed to set fulltext option"))]
336    SetFulltextOption {
337        source: datatypes::error::Error,
338        #[snafu(implicit)]
339        location: Location,
340    },
341
342    #[snafu(display("Failed to set SKIPPING index option"))]
343    SetSkippingIndexOption {
344        source: datatypes::error::Error,
345        #[snafu(implicit)]
346        location: Location,
347    },
348
349    #[snafu(display("Datatype error: {}", source))]
350    Datatype {
351        source: datatypes::error::Error,
352        #[snafu(implicit)]
353        location: Location,
354    },
355
356    #[snafu(display(
357        "Invalid partition number: {}, should be in range [2, 65536]",
358        partition_num
359    ))]
360    InvalidPartitionNumber {
361        partition_num: u32,
362        #[snafu(implicit)]
363        location: Location,
364    },
365
366    #[snafu(display("Unable to convert {} to datatype {:?}", value, datatype))]
367    ConvertStr {
368        value: String,
369        datatype: ConcreteDataType,
370        #[snafu(implicit)]
371        location: Location,
372    },
373
374    #[cfg(feature = "enterprise")]
375    #[snafu(display("Missing `{}` clause", name))]
376    MissingClause {
377        name: String,
378        #[snafu(implicit)]
379        location: Location,
380    },
381
382    #[cfg(feature = "enterprise")]
383    #[snafu(display("Unrecognized trigger webhook option key: {}", key))]
384    InvalidTriggerWebhookOption {
385        key: String,
386        #[snafu(implicit)]
387        location: Location,
388    },
389
390    #[cfg(feature = "enterprise")]
391    #[snafu(display("The execution interval cannot be negative"))]
392    NegativeInterval {
393        #[snafu(source)]
394        error: std::num::TryFromIntError,
395        #[snafu(implicit)]
396        location: Location,
397    },
398
399    #[cfg(feature = "enterprise")]
400    #[snafu(display("Must specify at least one notify channel"))]
401    MissingNotifyChannel {
402        #[snafu(implicit)]
403        location: Location,
404    },
405}
406
407impl ErrorExt for Error {
408    fn status_code(&self) -> StatusCode {
409        use Error::*;
410
411        match self {
412            UnsupportedDefaultValue { .. } | Unsupported { .. } => StatusCode::Unsupported,
413            Unexpected { .. }
414            | Syntax { .. }
415            | TQLSyntax { .. }
416            | MissingTimeIndex { .. }
417            | InvalidTimeIndex { .. }
418            | InvalidSql { .. }
419            | ParseSqlValue { .. }
420            | SqlTypeNotSupported { .. }
421            | ConcreteTypeNotSupported { .. }
422            | UnexpectedToken { .. }
423            | InvalidDefault { .. } => StatusCode::InvalidSyntax,
424
425            #[cfg(feature = "enterprise")]
426            MissingClause { .. } | MissingNotifyChannel { .. } => StatusCode::InvalidSyntax,
427
428            InvalidColumnOption { .. }
429            | InvalidTableOptionValue { .. }
430            | InvalidDatabaseName { .. }
431            | InvalidDatabaseOption { .. }
432            | ColumnTypeMismatch { .. }
433            | InvalidTableName { .. }
434            | InvalidFlowName { .. }
435            | InvalidFlowQuery { .. }
436            | InvalidSqlValue { .. }
437            | TimestampOverflow { .. }
438            | InvalidTableOption { .. }
439            | InvalidCast { .. }
440            | ConvertToLogicalExpression { .. }
441            | Simplification { .. }
442            | InvalidInterval { .. }
443            | InvalidUnaryOp { .. }
444            | InvalidPartitionNumber { .. }
445            | UnsupportedUnaryOp { .. }
446            | ConvertStr { .. } => StatusCode::InvalidArguments,
447
448            #[cfg(feature = "enterprise")]
449            InvalidTriggerWebhookOption { .. } | NegativeInterval { .. } => {
450                StatusCode::InvalidArguments
451            }
452
453            SerializeColumnDefaultConstraint { source, .. } => source.status_code(),
454            ConvertToGrpcDataType { source, .. } => source.status_code(),
455            Datatype { source, .. } => source.status_code(),
456            ConvertToDfStatement { .. } => StatusCode::Internal,
457            ConvertSqlValue { .. } | ConvertValue { .. } => StatusCode::Unsupported,
458
459            PermissionDenied { .. } => StatusCode::PermissionDenied,
460            SetFulltextOption { .. } | SetSkippingIndexOption { .. } => StatusCode::Unexpected,
461        }
462    }
463
464    fn as_any(&self) -> &dyn Any {
465        self
466    }
467}