1use std::any::Any;
18
19use arrow_schema::ArrowError;
20use common_error::ext::{BoxedError, ErrorExt};
21use common_error::status_code::StatusCode;
22use common_macro::stack_trace_debug;
23use datafusion_common::DataFusionError;
24use datatypes::data_type::ConcreteDataType;
25use snafu::{Location, Snafu};
26
27#[derive(Snafu)]
31#[snafu(visibility(pub))]
32#[stack_trace_debug]
33pub enum EvalError {
34 #[snafu(display("Type mismatch: expected {expected}, actual {actual}"))]
35 TypeMismatch {
36 expected: ConcreteDataType,
37 actual: ConcreteDataType,
38 #[snafu(implicit)]
39 location: Location,
40 },
41
42 #[snafu(display("Fail to unpack from value to given type: {msg}"))]
44 TryFromValue {
45 msg: String,
46 #[snafu(implicit)]
47 location: Location,
48 },
49
50 #[snafu(display("Fail to cast value of type {from} to given type {to}"))]
51 CastValue {
52 from: ConcreteDataType,
53 to: ConcreteDataType,
54 source: datatypes::Error,
55 #[snafu(implicit)]
56 location: Location,
57 },
58
59 #[snafu(display("{msg}"))]
60 DataType {
61 msg: String,
62 source: datatypes::Error,
63 #[snafu(implicit)]
64 location: Location,
65 },
66
67 #[snafu(display("Invalid argument: {reason}"))]
68 InvalidArgument {
69 reason: String,
70 #[snafu(implicit)]
71 location: Location,
72 },
73
74 #[snafu(display("Internal error: {reason}"))]
75 Internal {
76 reason: String,
77 #[snafu(implicit)]
78 location: Location,
79 },
80
81 #[snafu(display("Overflowed during evaluation"))]
82 Overflow {
83 #[snafu(implicit)]
84 location: Location,
85 },
86
87 #[snafu(display("Arrow error: {error:?}, context: {context}"))]
88 Arrow {
89 #[snafu(source)]
90 error: ArrowError,
91 context: String,
92 #[snafu(implicit)]
93 location: Location,
94 },
95
96 #[snafu(display("DataFusion error: {error:?}, context: {context}"))]
97 Datafusion {
98 #[snafu(source)]
99 error: DataFusionError,
100 context: String,
101 #[snafu(implicit)]
102 location: Location,
103 },
104
105 #[snafu(display("External error"))]
106 External {
107 #[snafu(implicit)]
108 location: Location,
109 source: BoxedError,
110 },
111}
112
113impl ErrorExt for EvalError {
114 fn status_code(&self) -> StatusCode {
115 use EvalError::*;
116 match self {
117 TypeMismatch { .. }
118 | TryFromValue { .. }
119 | InvalidArgument { .. }
120 | Overflow { .. } => StatusCode::InvalidArguments,
121
122 CastValue { source, .. } | DataType { source, .. } => source.status_code(),
123
124 Internal { .. } | Arrow { .. } | Datafusion { .. } | External { .. } => {
125 StatusCode::Internal
126 }
127 }
128 }
129
130 fn as_any(&self) -> &dyn Any {
131 self
132 }
133}