1use std::any::Any;
16use std::time::SystemTime;
17
18use common_error::ext::ErrorExt;
19use common_error::status_code::StatusCode;
20use common_macro::stack_trace_debug;
21use common_time::timestamp::TimeUnit;
22use datafusion::error::DataFusionError;
23use promql::error::Error as PromqlError;
24use promql_parser::parser::token::TokenType;
25use promql_parser::parser::{Expr as PromExpr, VectorMatchCardinality};
26use snafu::{Location, Snafu};
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 vector matches: {:?}", name))]
40 UnsupportedVectorMatch {
41 name: VectorMatchCardinality,
42 #[snafu(implicit)]
43 location: Location,
44 },
45
46 #[snafu(display("Unexpected token: {:?}", token))]
47 UnexpectedToken {
48 token: TokenType,
49 #[snafu(implicit)]
50 location: Location,
51 },
52
53 #[snafu(display("Internal error during building DataFusion plan"))]
54 DataFusionPlanning {
55 #[snafu(source)]
56 error: datafusion::error::DataFusionError,
57 #[snafu(implicit)]
58 location: Location,
59 },
60
61 #[snafu(display("Unexpected plan or expression: {}", desc))]
62 UnexpectedPlanExpr {
63 desc: String,
64 #[snafu(implicit)]
65 location: Location,
66 },
67
68 #[snafu(display("Unknown table type, downcast failed"))]
69 UnknownTable {
70 #[snafu(implicit)]
71 location: Location,
72 },
73
74 #[snafu(display("Cannot find time index column in table {}", table))]
75 TimeIndexNotFound {
76 table: String,
77 #[snafu(implicit)]
78 location: Location,
79 },
80
81 #[snafu(display("Cannot find value columns in table {}", table))]
82 ValueNotFound {
83 table: String,
84 #[snafu(implicit)]
85 location: Location,
86 },
87
88 #[snafu(display("Failed to create PromQL plan node"))]
89 PromqlPlanNode {
90 #[snafu(source)]
91 source: PromqlError,
92 #[snafu(implicit)]
93 location: Location,
94 },
95
96 #[snafu(display(
97 "Cannot accept multiple vector as function input, PromQL expr: {:?}",
98 expr,
99 ))]
100 MultipleVector {
101 expr: PromExpr,
102 #[snafu(implicit)]
103 location: Location,
104 },
105
106 #[snafu(display(
107 "Table (metric) name not found, this indicates a procedure error in PromQL planner"
108 ))]
109 TableNameNotFound {
110 #[snafu(implicit)]
111 location: Location,
112 },
113
114 #[snafu(display("General catalog error: "))]
115 Catalog {
116 #[snafu(implicit)]
117 location: Location,
118 source: catalog::error::Error,
119 },
120
121 #[snafu(display("Expect a range selector, but not found"))]
122 ExpectRangeSelector {
123 #[snafu(implicit)]
124 location: Location,
125 },
126
127 #[snafu(display("Zero range in range selector"))]
128 ZeroRangeSelector {
129 #[snafu(implicit)]
130 location: Location,
131 },
132
133 #[snafu(display("Subquery step must be positive"))]
134 ZeroSubqueryStep {
135 #[snafu(implicit)]
136 location: Location,
137 },
138
139 #[snafu(display(
140 "invalid expression type \"range vector\" for range query, must be Scalar or instant Vector"
141 ))]
142 RangeVectorInRangeQuery {
143 #[snafu(implicit)]
144 location: Location,
145 },
146
147 #[snafu(display(
148 "The end time must be greater than start time, start: {:?}, end: {:?}",
149 start,
150 end
151 ))]
152 InvalidTimeRange {
153 start: i64,
154 end: i64,
155 #[snafu(implicit)]
156 location: Location,
157 },
158
159 #[snafu(display(
160 "The subquery child window is outside the representable millisecond range: {}",
161 timestamp
162 ))]
163 SubqueryTimestampOutOfRange {
164 timestamp: String,
165 #[snafu(implicit)]
166 location: Location,
167 },
168
169 #[snafu(display("Cannot find column {col}"))]
170 ColumnNotFound {
171 col: String,
172 #[snafu(implicit)]
173 location: Location,
174 },
175
176 #[snafu(display("Found multiple metric matchers in selector"))]
177 MultipleMetricMatchers {
178 #[snafu(implicit)]
179 location: Location,
180 },
181
182 #[snafu(display("Expect a metric matcher, but not found"))]
183 NoMetricMatcher {
184 #[snafu(implicit)]
185 location: Location,
186 },
187
188 #[snafu(display("Invalid function argument for {}", fn_name))]
189 FunctionInvalidArgument {
190 fn_name: String,
191 #[snafu(implicit)]
192 location: Location,
193 },
194
195 #[snafu(display(
196 "Attempt to combine two tables with different column sets, left: {:?}, right: {:?}",
197 left,
198 right
199 ))]
200 CombineTableColumnMismatch {
201 left: Vec<String>,
202 right: Vec<String>,
203 #[snafu(implicit)]
204 location: Location,
205 },
206
207 #[snafu(display("Multi fields calculation is not supported in {}", operator))]
208 MultiFieldsNotSupported {
209 operator: String,
210 #[snafu(implicit)]
211 location: Location,
212 },
213
214 #[snafu(display("Matcher operator {matcher_op} is not supported for {matcher}"))]
215 UnsupportedMatcherOp {
216 matcher_op: String,
217 matcher: String,
218 #[snafu(implicit)]
219 location: Location,
220 },
221
222 #[snafu(display("Timestamp out of range for the `@` modifier: {}", timestamp))]
223 AtModifierTimestampOutOfRange {
224 timestamp: String,
225 #[snafu(implicit)]
226 location: Location,
227 },
228
229 #[snafu(display("Timestamp out of range: {} of {:?}", timestamp, unit))]
230 TimestampOutOfRange {
231 timestamp: i64,
232 unit: TimeUnit,
233 #[snafu(implicit)]
234 location: Location,
235 },
236
237 #[snafu(display("Time out of the representable millisecond range: {:?}", time))]
238 SystemTimeOutOfRange {
239 time: SystemTime,
240 #[snafu(implicit)]
241 location: Location,
242 },
243
244 #[snafu(display("Invalid regular expression in label_replace(): {}", regex))]
245 InvalidRegularExpression {
246 regex: String,
247 #[snafu(implicit)]
248 location: Location,
249 },
250
251 #[snafu(display("Invalid destination label name in label_replace(): {}", label_name))]
252 InvalidDestinationLabelName {
253 label_name: String,
254 #[snafu(implicit)]
255 location: Location,
256 },
257}
258
259impl ErrorExt for Error {
260 fn status_code(&self) -> StatusCode {
261 use Error::*;
262 match self {
263 TimeIndexNotFound { .. }
264 | ValueNotFound { .. }
265 | UnsupportedExpr { .. }
266 | UnexpectedToken { .. }
267 | MultipleVector { .. }
268 | ExpectRangeSelector { .. }
269 | ZeroRangeSelector { .. }
270 | RangeVectorInRangeQuery { .. }
271 | ZeroSubqueryStep { .. }
272 | InvalidTimeRange { .. }
273 | SubqueryTimestampOutOfRange { .. }
274 | ColumnNotFound { .. }
275 | FunctionInvalidArgument { .. }
276 | UnsupportedVectorMatch { .. }
277 | CombineTableColumnMismatch { .. }
278 | UnexpectedPlanExpr { .. }
279 | UnsupportedMatcherOp { .. }
280 | TimestampOutOfRange { .. }
281 | SystemTimeOutOfRange { .. }
282 | AtModifierTimestampOutOfRange { .. }
283 | InvalidRegularExpression { .. }
284 | InvalidDestinationLabelName { .. } => StatusCode::InvalidArguments,
285
286 UnknownTable { .. } => StatusCode::Internal,
287
288 PromqlPlanNode { source, .. } => source.status_code(),
289
290 DataFusionPlanning { .. } => StatusCode::PlanQuery,
291
292 TableNameNotFound { .. } => StatusCode::TableNotFound,
293
294 MultipleMetricMatchers { .. } | NoMetricMatcher { .. } => StatusCode::InvalidSyntax,
295
296 MultiFieldsNotSupported { .. } => StatusCode::Unsupported,
297 Catalog { source, .. } => source.status_code(),
298 }
299 }
300
301 fn as_any(&self) -> &dyn Any {
302 self
303 }
304}
305
306pub type Result<T> = std::result::Result<T, Error>;
307
308impl From<Error> for DataFusionError {
309 fn from(err: Error) -> Self {
310 DataFusionError::External(Box::new(err))
311 }
312}