Skip to main content

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