1use std::any::Any;
16
17use common_error::ext::ErrorExt;
18use common_error::status_code::StatusCode;
19use common_macro::stack_trace_debug;
20use common_time::timestamp::TimeUnit;
21use datafusion::error::DataFusionError;
22use promql::error::Error as PromqlError;
23use promql_parser::parser::token::TokenType;
24use promql_parser::parser::{Expr as PromExpr, VectorMatchCardinality};
25use snafu::{Location, Snafu};
26
27#[derive(Snafu)]
28#[snafu(visibility(pub))]
29#[stack_trace_debug]
30pub enum Error {
31 #[snafu(display("Unsupported expr type: {}", name))]
32 UnsupportedExpr {
33 name: String,
34 #[snafu(implicit)]
35 location: Location,
36 },
37
38 #[snafu(display("Unsupported vector matches: {:?}", name))]
39 UnsupportedVectorMatch {
40 name: VectorMatchCardinality,
41 #[snafu(implicit)]
42 location: Location,
43 },
44
45 #[snafu(display("Unexpected token: {:?}", token))]
46 UnexpectedToken {
47 token: TokenType,
48 #[snafu(implicit)]
49 location: Location,
50 },
51
52 #[snafu(display("Internal error during building DataFusion plan"))]
53 DataFusionPlanning {
54 #[snafu(source)]
55 error: datafusion::error::DataFusionError,
56 #[snafu(implicit)]
57 location: Location,
58 },
59
60 #[snafu(display("Unexpected plan or expression: {}", desc))]
61 UnexpectedPlanExpr {
62 desc: String,
63 #[snafu(implicit)]
64 location: Location,
65 },
66
67 #[snafu(display("Unknown table type, downcast failed"))]
68 UnknownTable {
69 #[snafu(implicit)]
70 location: Location,
71 },
72
73 #[snafu(display("Cannot find time index column in table {}", table))]
74 TimeIndexNotFound {
75 table: String,
76 #[snafu(implicit)]
77 location: Location,
78 },
79
80 #[snafu(display("Cannot find value columns in table {}", table))]
81 ValueNotFound {
82 table: String,
83 #[snafu(implicit)]
84 location: Location,
85 },
86
87 #[snafu(display("Failed to create PromQL plan node"))]
88 PromqlPlanNode {
89 #[snafu(source)]
90 source: PromqlError,
91 #[snafu(implicit)]
92 location: Location,
93 },
94
95 #[snafu(display(
96 "Cannot accept multiple vector as function input, PromQL expr: {:?}",
97 expr,
98 ))]
99 MultipleVector {
100 expr: PromExpr,
101 #[snafu(implicit)]
102 location: Location,
103 },
104
105 #[snafu(display(
106 "Table (metric) name not found, this indicates a procedure error in PromQL planner"
107 ))]
108 TableNameNotFound {
109 #[snafu(implicit)]
110 location: Location,
111 },
112
113 #[snafu(display("General catalog error: "))]
114 Catalog {
115 #[snafu(implicit)]
116 location: Location,
117 source: catalog::error::Error,
118 },
119
120 #[snafu(display("Expect a range selector, but not found"))]
121 ExpectRangeSelector {
122 #[snafu(implicit)]
123 location: Location,
124 },
125
126 #[snafu(display("Zero range in range selector"))]
127 ZeroRangeSelector {
128 #[snafu(implicit)]
129 location: Location,
130 },
131
132 #[snafu(display(
133 "The end time must be greater than start time, start: {:?}, end: {:?}",
134 start,
135 end
136 ))]
137 InvalidTimeRange {
138 start: i64,
139 end: i64,
140 #[snafu(implicit)]
141 location: Location,
142 },
143
144 #[snafu(display("Cannot find column {col}"))]
145 ColumnNotFound {
146 col: String,
147 #[snafu(implicit)]
148 location: Location,
149 },
150
151 #[snafu(display("Found multiple metric matchers in selector"))]
152 MultipleMetricMatchers {
153 #[snafu(implicit)]
154 location: Location,
155 },
156
157 #[snafu(display("Expect a metric matcher, but not found"))]
158 NoMetricMatcher {
159 #[snafu(implicit)]
160 location: Location,
161 },
162
163 #[snafu(display("Invalid function argument for {}", fn_name))]
164 FunctionInvalidArgument {
165 fn_name: String,
166 #[snafu(implicit)]
167 location: Location,
168 },
169
170 #[snafu(display(
171 "Attempt to combine two tables with different column sets, left: {:?}, right: {:?}",
172 left,
173 right
174 ))]
175 CombineTableColumnMismatch {
176 left: Vec<String>,
177 right: Vec<String>,
178 #[snafu(implicit)]
179 location: Location,
180 },
181
182 #[snafu(display("Multi fields calculation is not supported in {}", operator))]
183 MultiFieldsNotSupported {
184 operator: String,
185 #[snafu(implicit)]
186 location: Location,
187 },
188
189 #[snafu(display("Matcher operator {matcher_op} is not supported for {matcher}"))]
190 UnsupportedMatcherOp {
191 matcher_op: String,
192 matcher: String,
193 #[snafu(implicit)]
194 location: Location,
195 },
196
197 #[snafu(display("Timestamp out of range: {} of {:?}", timestamp, unit))]
198 TimestampOutOfRange {
199 timestamp: i64,
200 unit: TimeUnit,
201 #[snafu(implicit)]
202 location: Location,
203 },
204}
205
206impl ErrorExt for Error {
207 fn status_code(&self) -> StatusCode {
208 use Error::*;
209 match self {
210 TimeIndexNotFound { .. }
211 | ValueNotFound { .. }
212 | UnsupportedExpr { .. }
213 | UnexpectedToken { .. }
214 | MultipleVector { .. }
215 | ExpectRangeSelector { .. }
216 | ZeroRangeSelector { .. }
217 | InvalidTimeRange { .. }
218 | ColumnNotFound { .. }
219 | FunctionInvalidArgument { .. }
220 | UnsupportedVectorMatch { .. }
221 | CombineTableColumnMismatch { .. }
222 | UnexpectedPlanExpr { .. }
223 | UnsupportedMatcherOp { .. }
224 | TimestampOutOfRange { .. } => StatusCode::InvalidArguments,
225
226 UnknownTable { .. } => StatusCode::Internal,
227
228 PromqlPlanNode { source, .. } => source.status_code(),
229
230 DataFusionPlanning { .. } => StatusCode::PlanQuery,
231
232 TableNameNotFound { .. } => StatusCode::TableNotFound,
233
234 MultipleMetricMatchers { .. } | NoMetricMatcher { .. } => StatusCode::InvalidSyntax,
235
236 MultiFieldsNotSupported { .. } => StatusCode::Unsupported,
237 Catalog { source, .. } => source.status_code(),
238 }
239 }
240
241 fn as_any(&self) -> &dyn Any {
242 self
243 }
244}
245
246pub type Result<T> = std::result::Result<T, Error>;
247
248impl From<Error> for DataFusionError {
249 fn from(err: Error) -> Self {
250 DataFusionError::External(Box::new(err))
251 }
252}