1use 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#[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 #[snafu(display("Invalid SQL syntax"))]
59 Syntax {
60 #[snafu(source)]
61 error: ParserError,
62 #[snafu(implicit)]
63 location: Location,
64 },
65
66 #[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}