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