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 table name: {}", name))]
168    InvalidTableName {
169        name: String,
170        #[snafu(implicit)]
171        location: Location,
172    },
173
174    #[snafu(display("Invalid flow name: {}", name))]
175    InvalidFlowName {
176        name: String,
177        #[snafu(implicit)]
178        location: Location,
179    },
180
181    #[cfg(feature = "enterprise")]
182    #[snafu(display("Invalid trigger name: {}", name))]
183    InvalidTriggerName {
184        name: String,
185        #[snafu(implicit)]
186        location: Location,
187    },
188
189    #[snafu(display("Invalid flow query: {}", reason))]
190    InvalidFlowQuery {
191        reason: String,
192        #[snafu(implicit)]
193        location: Location,
194    },
195
196    #[snafu(display("Invalid default constraint, column: {}", column))]
197    InvalidDefault {
198        column: String,
199        #[snafu(implicit)]
200        location: Location,
201        source: datatypes::error::Error,
202    },
203
204    #[snafu(display("Unrecognized table option key: {}", key))]
205    InvalidTableOption {
206        key: String,
207        #[snafu(implicit)]
208        location: Location,
209    },
210
211    #[snafu(display("Invalid expr as option value, error: {error}"))]
212    InvalidExprAsOptionValue {
213        error: String,
214        #[snafu(implicit)]
215        location: Location,
216    },
217
218    #[snafu(display("Failed to serialize column default constraint"))]
219    SerializeColumnDefaultConstraint {
220        #[snafu(implicit)]
221        location: Location,
222        source: datatypes::error::Error,
223    },
224
225    #[snafu(display("Failed to convert data type to gRPC data type defined in proto"))]
226    ConvertToGrpcDataType {
227        #[snafu(implicit)]
228        location: Location,
229        source: api::error::Error,
230    },
231
232    #[snafu(display("Unable to convert statement {} to DataFusion statement", statement))]
233    ConvertToDfStatement {
234        statement: String,
235        #[snafu(implicit)]
236        location: Location,
237    },
238
239    #[snafu(display("Unable to convert value {} to sql value", value))]
240    ConvertValue {
241        value: Value,
242        #[snafu(implicit)]
243        location: Location,
244    },
245
246    #[snafu(display("Failed to convert to logical TQL expression"))]
247    ConvertToLogicalExpression {
248        #[snafu(source)]
249        error: DataFusionError,
250        #[snafu(implicit)]
251        location: Location,
252    },
253
254    #[snafu(display("Failed to simplify TQL expression"))]
255    Simplification {
256        #[snafu(source)]
257        error: DataFusionError,
258        #[snafu(implicit)]
259        location: Location,
260    },
261
262    #[snafu(display(
263        "Permission denied while operating catalog {} from current catalog {}",
264        target,
265        current
266    ))]
267    PermissionDenied {
268        target: String,
269        current: String,
270        #[snafu(implicit)]
271        location: Location,
272    },
273
274    #[snafu(display("Failed to set fulltext option"))]
275    SetFulltextOption {
276        source: datatypes::error::Error,
277        #[snafu(implicit)]
278        location: Location,
279    },
280
281    #[snafu(display("Failed to set SKIPPING index option"))]
282    SetSkippingIndexOption {
283        source: datatypes::error::Error,
284        #[snafu(implicit)]
285        location: Location,
286    },
287
288    #[snafu(display("Failed to set VECTOR index option"))]
289    SetVectorIndexOption {
290        source: datatypes::error::Error,
291        #[snafu(implicit)]
292        location: Location,
293    },
294
295    #[snafu(display(
296        "Invalid partition number: {}, should be in range [2, 65536]",
297        partition_num
298    ))]
299    InvalidPartitionNumber {
300        partition_num: u32,
301        #[snafu(implicit)]
302        location: Location,
303    },
304
305    #[cfg(feature = "enterprise")]
306    #[snafu(display("Missing `{}` clause", name))]
307    MissingClause {
308        name: String,
309        #[snafu(implicit)]
310        location: Location,
311    },
312
313    #[cfg(feature = "enterprise")]
314    #[snafu(display("Unrecognized trigger webhook option key: {}", key))]
315    InvalidTriggerWebhookOption {
316        key: String,
317        #[snafu(implicit)]
318        location: Location,
319    },
320
321    #[cfg(feature = "enterprise")]
322    #[snafu(display("Must specify at least one notify channel"))]
323    MissingNotifyChannel {
324        #[snafu(implicit)]
325        location: Location,
326    },
327
328    #[snafu(display("Sql common error"))]
329    SqlCommon {
330        source: common_sql::error::Error,
331        #[snafu(implicit)]
332        location: Location,
333    },
334
335    #[cfg(feature = "enterprise")]
336    #[snafu(display("Duplicate clauses `{}` in a statement", clause))]
337    DuplicateClause {
338        clause: String,
339        #[snafu(implicit)]
340        location: Location,
341    },
342
343    #[snafu(display("Failed to set JSON structure settings: {value}"))]
344    SetJsonStructureSettings {
345        value: String,
346        source: datatypes::error::Error,
347        #[snafu(implicit)]
348        location: Location,
349    },
350}
351
352impl ErrorExt for Error {
353    fn status_code(&self) -> StatusCode {
354        use Error::*;
355
356        match self {
357            Unsupported { .. } => StatusCode::Unsupported,
358            Unexpected { .. }
359            | Syntax { .. }
360            | TQLSyntax { .. }
361            | MissingTimeIndex { .. }
362            | InvalidTimeIndex { .. }
363            | InvalidSql { .. }
364            | ParseSqlValue { .. }
365            | SqlTypeNotSupported { .. }
366            | ConcreteTypeNotSupported { .. }
367            | UnexpectedToken { .. }
368            | InvalidDefault { .. } => StatusCode::InvalidSyntax,
369
370            #[cfg(feature = "enterprise")]
371            MissingClause { .. } | MissingNotifyChannel { .. } | DuplicateClause { .. } => {
372                StatusCode::InvalidSyntax
373            }
374
375            InvalidColumnOption { .. }
376            | InvalidExprAsOptionValue { .. }
377            | InvalidDatabaseName { .. }
378            | InvalidDatabaseOption { .. }
379            | ColumnTypeMismatch { .. }
380            | InvalidTableName { .. }
381            | InvalidFlowName { .. }
382            | InvalidFlowQuery { .. }
383            | InvalidTableOption { .. }
384            | ConvertToLogicalExpression { .. }
385            | Simplification { .. }
386            | InvalidInterval { .. }
387            | InvalidPartitionNumber { .. } => StatusCode::InvalidArguments,
388
389            #[cfg(feature = "enterprise")]
390            InvalidTriggerName { .. } => StatusCode::InvalidArguments,
391
392            #[cfg(feature = "enterprise")]
393            InvalidTriggerWebhookOption { .. } => StatusCode::InvalidArguments,
394
395            SerializeColumnDefaultConstraint { source, .. }
396            | SetJsonStructureSettings { source, .. } => source.status_code(),
397
398            ConvertToGrpcDataType { source, .. } => source.status_code(),
399            SqlCommon { source, .. } => source.status_code(),
400            ConvertToDfStatement { .. } => StatusCode::Internal,
401            ConvertValue { .. } => StatusCode::Unsupported,
402
403            PermissionDenied { .. } => StatusCode::PermissionDenied,
404            SetFulltextOption { .. }
405            | SetSkippingIndexOption { .. }
406            | SetVectorIndexOption { .. } => StatusCode::Unexpected,
407        }
408    }
409
410    fn as_any(&self) -> &dyn Any {
411        self
412    }
413}