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(
289 "Invalid partition number: {}, should be in range [2, 65536]",
290 partition_num
291 ))]
292 InvalidPartitionNumber {
293 partition_num: u32,
294 #[snafu(implicit)]
295 location: Location,
296 },
297
298 #[cfg(feature = "enterprise")]
299 #[snafu(display("Missing `{}` clause", name))]
300 MissingClause {
301 name: String,
302 #[snafu(implicit)]
303 location: Location,
304 },
305
306 #[cfg(feature = "enterprise")]
307 #[snafu(display("Unrecognized trigger webhook option key: {}", key))]
308 InvalidTriggerWebhookOption {
309 key: String,
310 #[snafu(implicit)]
311 location: Location,
312 },
313
314 #[cfg(feature = "enterprise")]
315 #[snafu(display("Must specify at least one notify channel"))]
316 MissingNotifyChannel {
317 #[snafu(implicit)]
318 location: Location,
319 },
320
321 #[snafu(display("Sql common error"))]
322 SqlCommon {
323 source: common_sql::error::Error,
324 #[snafu(implicit)]
325 location: Location,
326 },
327
328 #[cfg(feature = "enterprise")]
329 #[snafu(display("Duplicate clauses `{}` in a statement", clause))]
330 DuplicateClause {
331 clause: String,
332 #[snafu(implicit)]
333 location: Location,
334 },
335
336 #[snafu(display("Failed to set JSON structure settings: {value}"))]
337 SetJsonStructureSettings {
338 value: String,
339 source: datatypes::error::Error,
340 #[snafu(implicit)]
341 location: Location,
342 },
343}
344
345impl ErrorExt for Error {
346 fn status_code(&self) -> StatusCode {
347 use Error::*;
348
349 match self {
350 Unsupported { .. } => StatusCode::Unsupported,
351 Unexpected { .. }
352 | Syntax { .. }
353 | TQLSyntax { .. }
354 | MissingTimeIndex { .. }
355 | InvalidTimeIndex { .. }
356 | InvalidSql { .. }
357 | ParseSqlValue { .. }
358 | SqlTypeNotSupported { .. }
359 | ConcreteTypeNotSupported { .. }
360 | UnexpectedToken { .. }
361 | InvalidDefault { .. } => StatusCode::InvalidSyntax,
362
363 #[cfg(feature = "enterprise")]
364 MissingClause { .. } | MissingNotifyChannel { .. } | DuplicateClause { .. } => {
365 StatusCode::InvalidSyntax
366 }
367
368 InvalidColumnOption { .. }
369 | InvalidExprAsOptionValue { .. }
370 | InvalidDatabaseName { .. }
371 | InvalidDatabaseOption { .. }
372 | ColumnTypeMismatch { .. }
373 | InvalidTableName { .. }
374 | InvalidFlowName { .. }
375 | InvalidFlowQuery { .. }
376 | InvalidTableOption { .. }
377 | ConvertToLogicalExpression { .. }
378 | Simplification { .. }
379 | InvalidInterval { .. }
380 | InvalidPartitionNumber { .. } => StatusCode::InvalidArguments,
381
382 #[cfg(feature = "enterprise")]
383 InvalidTriggerName { .. } => StatusCode::InvalidArguments,
384
385 #[cfg(feature = "enterprise")]
386 InvalidTriggerWebhookOption { .. } => StatusCode::InvalidArguments,
387
388 SerializeColumnDefaultConstraint { source, .. }
389 | SetJsonStructureSettings { source, .. } => source.status_code(),
390
391 ConvertToGrpcDataType { source, .. } => source.status_code(),
392 SqlCommon { source, .. } => source.status_code(),
393 ConvertToDfStatement { .. } => StatusCode::Internal,
394 ConvertValue { .. } => StatusCode::Unsupported,
395
396 PermissionDenied { .. } => StatusCode::PermissionDenied,
397 SetFulltextOption { .. } | SetSkippingIndexOption { .. } => StatusCode::Unexpected,
398 }
399 }
400
401 fn as_any(&self) -> &dyn Any {
402 self
403 }
404}