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