1use std::any::Any;
16use std::time::{Duration, TryFromFloatSecsError};
17
18use common_error::ext::{BoxedError, ErrorExt};
19use common_error::status_code::StatusCode;
20use common_macro::stack_trace_debug;
21use common_query::error::datafusion_status_code;
22use datafusion::error::DataFusionError;
23use datatypes::prelude::ConcreteDataType;
24use datatypes::value::Value;
25use snafu::{Location, Snafu};
26use store_api::storage::RegionId;
27
28#[derive(Snafu)]
29#[snafu(visibility(pub))]
30#[stack_trace_debug]
31pub enum Error {
32 #[snafu(display("Unsupported expr type: {}", name))]
33 UnsupportedExpr {
34 name: String,
35 #[snafu(implicit)]
36 location: Location,
37 },
38
39 #[snafu(display("Unsupported show variable: {}", name))]
40 UnsupportedVariable {
41 name: String,
42 #[snafu(implicit)]
43 location: Location,
44 },
45
46 #[snafu(display("Operation {} not implemented yet", operation))]
47 Unimplemented {
48 operation: String,
49 #[snafu(implicit)]
50 location: Location,
51 },
52
53 #[snafu(display("General catalog error"))]
54 Catalog {
55 source: catalog::error::Error,
56 #[snafu(implicit)]
57 location: Location,
58 },
59
60 #[snafu(display("Partition rule manager error"))]
61 PartitionRuleManager {
62 source: partition::error::Error,
63 #[snafu(implicit)]
64 location: Location,
65 },
66
67 #[snafu(display("Table not found: {}", table))]
68 TableNotFound {
69 table: String,
70 #[snafu(implicit)]
71 location: Location,
72 },
73
74 #[snafu(display("Failed to create RecordBatch"))]
75 CreateRecordBatch {
76 source: common_recordbatch::error::Error,
77 #[snafu(implicit)]
78 location: Location,
79 },
80
81 #[snafu(display("Failure during query execution"))]
82 QueryExecution {
83 source: BoxedError,
84 #[snafu(implicit)]
85 location: Location,
86 },
87
88 #[snafu(display("Failure during query planning"))]
89 QueryPlan {
90 source: BoxedError,
91 #[snafu(implicit)]
92 location: Location,
93 },
94
95 #[snafu(display("Failure during query parsing, query: {}", query))]
96 QueryParse {
97 query: String,
98 source: BoxedError,
99 #[snafu(implicit)]
100 location: Location,
101 },
102
103 #[snafu(display("Illegal access to catalog: {} and schema: {}", catalog, schema))]
104 QueryAccessDenied {
105 catalog: String,
106 schema: String,
107 #[snafu(implicit)]
108 location: Location,
109 },
110
111 #[snafu(display("The SQL string has multiple statements, query: {}", query))]
112 MultipleStatements {
113 query: String,
114 #[snafu(implicit)]
115 location: Location,
116 },
117
118 #[snafu(display("Failed to parse timestamp `{}`", raw))]
119 ParseTimestamp {
120 raw: String,
121 #[snafu(source)]
122 error: chrono::ParseError,
123 #[snafu(implicit)]
124 location: Location,
125 },
126
127 #[snafu(display("Failed to parse float number `{}`", raw))]
128 ParseFloat {
129 raw: String,
130 #[snafu(source)]
131 error: std::num::ParseFloatError,
132 #[snafu(implicit)]
133 location: Location,
134 },
135
136 #[snafu(transparent)]
137 DataFusion {
138 #[snafu(source)]
139 error: DataFusionError,
140 #[snafu(implicit)]
141 location: Location,
142 },
143
144 #[snafu(display("General SQL error"))]
145 Sql {
146 #[snafu(implicit)]
147 location: Location,
148 source: sql::error::Error,
149 },
150
151 #[snafu(display("Failed to plan SQL"))]
152 PlanSql {
153 #[snafu(source)]
154 error: DataFusionError,
155 #[snafu(implicit)]
156 location: Location,
157 },
158
159 #[snafu(display("Timestamp column for table '{table_name}' is missing!"))]
160 MissingTimestampColumn {
161 table_name: String,
162 #[snafu(implicit)]
163 location: Location,
164 },
165
166 #[snafu(display("Failed to convert value to sql value: {}", value))]
167 ConvertSqlValue {
168 value: Value,
169 source: sql::error::Error,
170 #[snafu(implicit)]
171 location: Location,
172 },
173
174 #[snafu(display("Failed to convert concrete type to sql type: {:?}", datatype))]
175 ConvertSqlType {
176 datatype: ConcreteDataType,
177 source: sql::error::Error,
178 #[snafu(implicit)]
179 location: Location,
180 },
181
182 #[snafu(display("Missing required field: {}", name))]
183 MissingRequiredField {
184 name: String,
185 #[snafu(implicit)]
186 location: Location,
187 },
188
189 #[snafu(display("Failed to regex"))]
190 BuildRegex {
191 #[snafu(implicit)]
192 location: Location,
193 #[snafu(source)]
194 error: regex::Error,
195 },
196
197 #[snafu(display("Failed to build data source backend"))]
198 BuildBackend {
199 source: common_datasource::error::Error,
200 #[snafu(implicit)]
201 location: Location,
202 },
203
204 #[snafu(display("Failed to list objects"))]
205 ListObjects {
206 source: common_datasource::error::Error,
207 #[snafu(implicit)]
208 location: Location,
209 },
210
211 #[snafu(display("Failed to parse file format"))]
212 ParseFileFormat {
213 source: common_datasource::error::Error,
214 #[snafu(implicit)]
215 location: Location,
216 },
217
218 #[snafu(display("Failed to infer schema"))]
219 InferSchema {
220 source: common_datasource::error::Error,
221 #[snafu(implicit)]
222 location: Location,
223 },
224
225 #[snafu(display("Failed to convert datafusion schema"))]
226 ConvertSchema {
227 source: datatypes::error::Error,
228 #[snafu(implicit)]
229 location: Location,
230 },
231
232 #[snafu(display("Unknown table type, downcast failed"))]
233 UnknownTable {
234 #[snafu(implicit)]
235 location: Location,
236 },
237
238 #[snafu(display("Cannot find time index column in table {}", table))]
239 TimeIndexNotFound {
240 table: String,
241 #[snafu(implicit)]
242 location: Location,
243 },
244
245 #[snafu(display("Failed to add duration '{:?}' to SystemTime, overflowed", duration))]
246 AddSystemTimeOverflow {
247 duration: Duration,
248 #[snafu(implicit)]
249 location: Location,
250 },
251
252 #[snafu(display(
253 "Column schema incompatible, column: {}, file_type: {}, table_type: {}",
254 column,
255 file_type,
256 table_type
257 ))]
258 ColumnSchemaIncompatible {
259 column: String,
260 file_type: ConcreteDataType,
261 table_type: ConcreteDataType,
262 #[snafu(implicit)]
263 location: Location,
264 },
265
266 #[snafu(display("Column schema has no default value, column: {}", column))]
267 ColumnSchemaNoDefault {
268 column: String,
269 #[snafu(implicit)]
270 location: Location,
271 },
272
273 #[snafu(display("Region query error"))]
274 RegionQuery {
275 source: BoxedError,
276 #[snafu(implicit)]
277 location: Location,
278 },
279
280 #[snafu(display("Table mutation error"))]
281 TableMutation {
282 source: common_query::error::Error,
283 #[snafu(implicit)]
284 location: Location,
285 },
286
287 #[snafu(display("Missing table mutation handler"))]
288 MissingTableMutationHandler {
289 #[snafu(implicit)]
290 location: Location,
291 },
292
293 #[snafu(display("Range Query: {}", msg))]
294 RangeQuery {
295 msg: String,
296 #[snafu(implicit)]
297 location: Location,
298 },
299
300 #[snafu(display(
301 "Failed to get metadata from engine {} for region_id {}",
302 engine,
303 region_id,
304 ))]
305 GetRegionMetadata {
306 engine: String,
307 region_id: RegionId,
308 #[snafu(implicit)]
309 location: Location,
310 source: BoxedError,
311 },
312
313 #[snafu(display("Cannot change read-only table: {}", table))]
314 TableReadOnly {
315 table: String,
316 #[snafu(implicit)]
317 location: Location,
318 },
319
320 #[snafu(display("Failed to get fulltext options"))]
321 GetFulltextOptions {
322 source: datatypes::error::Error,
323 #[snafu(implicit)]
324 location: Location,
325 },
326
327 #[snafu(display("Failed to get SKIPPING index options"))]
328 GetSkippingIndexOptions {
329 source: datatypes::error::Error,
330 #[snafu(implicit)]
331 location: Location,
332 },
333
334 #[snafu(display("Failed to get VECTOR index options"))]
335 GetVectorIndexOptions {
336 source: datatypes::error::Error,
337 #[snafu(implicit)]
338 location: Location,
339 },
340
341 #[snafu(display(
342 "Column schema mismatch in CTE {}, original: {:?}, expected: {:?}",
343 cte_name,
344 original,
345 expected,
346 ))]
347 CteColumnSchemaMismatch {
348 cte_name: String,
349 original: Vec<String>,
350 expected: Vec<String>,
351 #[snafu(implicit)]
352 location: Location,
353 },
354
355 #[snafu(display("Failed to convert value for region pruning"))]
356 ConvertValue {
357 source: datatypes::error::Error,
358 #[snafu(implicit)]
359 location: Location,
360 },
361
362 #[snafu(display("Failed to convert float seconds to duration, raw: {}", raw))]
363 TryIntoDuration {
364 raw: String,
365 #[snafu(source)]
366 error: TryFromFloatSecsError,
367 #[snafu(implicit)]
368 location: Location,
369 },
370
371 #[snafu(transparent)]
372 Datatypes {
373 source: datatypes::error::Error,
374 #[snafu(implicit)]
375 location: Location,
376 },
377}
378
379impl ErrorExt for Error {
380 fn status_code(&self) -> StatusCode {
381 use Error::*;
382
383 match self {
384 QueryParse { .. } | MultipleStatements { .. } | RangeQuery { .. } => {
385 StatusCode::InvalidSyntax
386 }
387 UnsupportedExpr { .. }
388 | Unimplemented { .. }
389 | UnknownTable { .. }
390 | TimeIndexNotFound { .. }
391 | ParseTimestamp { .. }
392 | ParseFloat { .. }
393 | MissingRequiredField { .. }
394 | BuildRegex { .. }
395 | ConvertSchema { .. }
396 | AddSystemTimeOverflow { .. }
397 | ColumnSchemaIncompatible { .. }
398 | UnsupportedVariable { .. }
399 | ColumnSchemaNoDefault { .. }
400 | CteColumnSchemaMismatch { .. }
401 | ConvertValue { .. }
402 | TryIntoDuration { .. } => StatusCode::InvalidArguments,
403
404 BuildBackend { .. } | ListObjects { .. } => StatusCode::StorageUnavailable,
405
406 TableNotFound { .. } => StatusCode::TableNotFound,
407
408 ParseFileFormat { source, .. } | InferSchema { source, .. } => source.status_code(),
409
410 QueryAccessDenied { .. } => StatusCode::AccessDenied,
411 Catalog { source, .. } => source.status_code(),
412 CreateRecordBatch { source, .. } => source.status_code(),
413 PartitionRuleManager { source, .. } => source.status_code(),
414 QueryExecution { source, .. } | QueryPlan { source, .. } => source.status_code(),
415 PlanSql { error, .. } => {
416 datafusion_status_code::<Self>(error, Some(StatusCode::PlanQuery))
417 }
418
419 DataFusion { error, .. } => datafusion_status_code::<Self>(error, None),
420
421 MissingTimestampColumn { .. } => StatusCode::EngineExecuteQuery,
422 Sql { source, .. } => source.status_code(),
423
424 ConvertSqlType { source, .. } | ConvertSqlValue { source, .. } => source.status_code(),
425
426 RegionQuery { source, .. } => source.status_code(),
427 TableMutation { source, .. } => source.status_code(),
428 MissingTableMutationHandler { .. } => StatusCode::Unexpected,
429 GetRegionMetadata { .. } => StatusCode::RegionNotReady,
430 TableReadOnly { .. } => StatusCode::Unsupported,
431
432 GetFulltextOptions { source, .. }
433 | GetSkippingIndexOptions { source, .. }
434 | GetVectorIndexOptions { source, .. }
435 | Datatypes { source, .. } => source.status_code(),
436 }
437 }
438
439 fn as_any(&self) -> &dyn Any {
440 self
441 }
442}
443
444pub type Result<T> = std::result::Result<T, Error>;
445
446impl From<Error> for DataFusionError {
447 fn from(e: Error) -> DataFusionError {
448 DataFusionError::External(Box::new(e))
449 }
450}