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("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}