1use 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#[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 #[snafu(display("Invalid SQL syntax"))]
76 Syntax {
77 #[snafu(source)]
78 error: ParserError,
79 #[snafu(implicit)]
80 location: Location,
81 },
82
83 #[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}