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