Skip to main content

query/promql/
error.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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}