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("Division by zero"))]
35 DivisionByZero {
36 #[snafu(implicit)]
37 location: Location,
38 },
39
40 #[snafu(display("Type mismatch: expected {expected}, actual {actual}"))]
41 TypeMismatch {
42 expected: ConcreteDataType,
43 actual: ConcreteDataType,
44 #[snafu(implicit)]
45 location: Location,
46 },
47
48 #[snafu(display("Fail to unpack from value to given type: {msg}"))]
50 TryFromValue {
51 msg: String,
52 #[snafu(implicit)]
53 location: Location,
54 },
55
56 #[snafu(display("Fail to cast value of type {from} to given type {to}"))]
57 CastValue {
58 from: ConcreteDataType,
59 to: ConcreteDataType,
60 source: datatypes::Error,
61 #[snafu(implicit)]
62 location: Location,
63 },
64
65 #[snafu(display("{msg}"))]
66 DataType {
67 msg: String,
68 source: datatypes::Error,
69 #[snafu(implicit)]
70 location: Location,
71 },
72
73 #[snafu(display("Invalid argument: {reason}"))]
74 InvalidArgument {
75 reason: String,
76 #[snafu(implicit)]
77 location: Location,
78 },
79
80 #[snafu(display("Internal error: {reason}"))]
81 Internal {
82 reason: String,
83 #[snafu(implicit)]
84 location: Location,
85 },
86
87 #[snafu(display("Optimize error: {reason}"))]
88 Optimize {
89 reason: String,
90 #[snafu(implicit)]
91 location: Location,
92 },
93
94 #[snafu(display("Overflowed during evaluation"))]
95 Overflow {
96 #[snafu(implicit)]
97 location: Location,
98 },
99
100 #[snafu(display("Incoming data already expired by {} ms", expired_by))]
101 DataAlreadyExpired {
102 expired_by: i64,
103 #[snafu(implicit)]
104 location: Location,
105 },
106
107 #[snafu(display("Arrow error: {error:?}, context: {context}"))]
108 Arrow {
109 #[snafu(source)]
110 error: ArrowError,
111 context: String,
112 #[snafu(implicit)]
113 location: Location,
114 },
115
116 #[snafu(display("DataFusion error: {error:?}, context: {context}"))]
117 Datafusion {
118 #[snafu(source)]
119 error: DataFusionError,
120 context: String,
121 #[snafu(implicit)]
122 location: Location,
123 },
124
125 #[snafu(display("External error"))]
126 External {
127 #[snafu(implicit)]
128 location: Location,
129 source: BoxedError,
130 },
131}
132
133impl ErrorExt for EvalError {
134 fn status_code(&self) -> StatusCode {
135 use EvalError::*;
136 match self {
137 DivisionByZero { .. }
138 | TypeMismatch { .. }
139 | TryFromValue { .. }
140 | DataAlreadyExpired { .. }
141 | InvalidArgument { .. }
142 | Overflow { .. } => StatusCode::InvalidArguments,
143
144 CastValue { source, .. } | DataType { source, .. } => source.status_code(),
145
146 Internal { .. }
147 | Optimize { .. }
148 | Arrow { .. }
149 | Datafusion { .. }
150 | External { .. } => StatusCode::Internal,
151 }
152 }
153
154 fn as_any(&self) -> &dyn Any {
155 self
156 }
157}