use std::any::Any;
use arrow_schema::ArrowError;
use common_error::ext::{BoxedError, ErrorExt};
use common_error::status_code::StatusCode;
use common_macro::stack_trace_debug;
use datafusion_common::DataFusionError;
use datatypes::data_type::ConcreteDataType;
use snafu::{Location, Snafu};
#[derive(Snafu)]
#[snafu(visibility(pub))]
#[stack_trace_debug]
pub enum EvalError {
#[snafu(display("Division by zero"))]
DivisionByZero {
#[snafu(implicit)]
location: Location,
},
#[snafu(display("Type mismatch: expected {expected}, actual {actual}"))]
TypeMismatch {
expected: ConcreteDataType,
actual: ConcreteDataType,
#[snafu(implicit)]
location: Location,
},
#[snafu(display("Fail to unpack from value to given type: {msg}"))]
TryFromValue {
msg: String,
#[snafu(implicit)]
location: Location,
},
#[snafu(display("Fail to cast value of type {from} to given type {to}"))]
CastValue {
from: ConcreteDataType,
to: ConcreteDataType,
source: datatypes::Error,
#[snafu(implicit)]
location: Location,
},
#[snafu(display("{msg}"))]
DataType {
msg: String,
source: datatypes::Error,
#[snafu(implicit)]
location: Location,
},
#[snafu(display("Invalid argument: {reason}"))]
InvalidArgument {
reason: String,
#[snafu(implicit)]
location: Location,
},
#[snafu(display("Internal error: {reason}"))]
Internal {
reason: String,
#[snafu(implicit)]
location: Location,
},
#[snafu(display("Optimize error: {reason}"))]
Optimize {
reason: String,
#[snafu(implicit)]
location: Location,
},
#[snafu(display("Overflowed during evaluation"))]
Overflow {
#[snafu(implicit)]
location: Location,
},
#[snafu(display("Incoming data already expired by {} ms", expired_by))]
DataAlreadyExpired {
expired_by: i64,
#[snafu(implicit)]
location: Location,
},
#[snafu(display("Arrow error: {error:?}, context: {context}"))]
Arrow {
#[snafu(source)]
error: ArrowError,
context: String,
#[snafu(implicit)]
location: Location,
},
#[snafu(display("DataFusion error: {error:?}, context: {context}"))]
Datafusion {
#[snafu(source)]
error: DataFusionError,
context: String,
#[snafu(implicit)]
location: Location,
},
#[snafu(display("External error"))]
External {
#[snafu(implicit)]
location: Location,
source: BoxedError,
},
}
impl ErrorExt for EvalError {
fn status_code(&self) -> StatusCode {
use EvalError::*;
match self {
DivisionByZero { .. }
| TypeMismatch { .. }
| TryFromValue { .. }
| DataAlreadyExpired { .. }
| InvalidArgument { .. }
| Overflow { .. } => StatusCode::InvalidArguments,
CastValue { source, .. } | DataType { source, .. } => source.status_code(),
Internal { .. }
| Optimize { .. }
| Arrow { .. }
| Datafusion { .. }
| External { .. } => StatusCode::Internal,
}
}
fn as_any(&self) -> &dyn Any {
self
}
}