Skip to main content

promql_parser/parser/
function.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::collections::{HashMap, HashSet};
16use std::fmt;
17
18use lazy_static::lazy_static;
19
20use crate::parser::value::ValueType;
21use crate::parser::{Expr, Prettier};
22use crate::util::join_vector;
23
24/// called by func in Call
25#[derive(Debug, Clone, PartialEq, Eq)]
26#[cfg_attr(feature = "ser", derive(serde::Serialize))]
27pub struct FunctionArgs {
28    pub args: Vec<Box<Expr>>,
29}
30
31impl FunctionArgs {
32    pub fn empty_args() -> Self {
33        Self { args: vec![] }
34    }
35
36    pub fn new_args(expr: Expr) -> Self {
37        Self {
38            args: vec![Box::new(expr)],
39        }
40    }
41
42    pub fn append_args(mut self: FunctionArgs, expr: Expr) -> Self {
43        self.args.push(Box::new(expr));
44        self
45    }
46
47    pub fn is_empty(&self) -> bool {
48        self.args.is_empty()
49    }
50
51    pub fn len(&self) -> usize {
52        self.args.len()
53    }
54
55    pub fn first(&self) -> Option<Box<Expr>> {
56        self.args.first().cloned()
57    }
58
59    pub fn last(&self) -> Option<Box<Expr>> {
60        self.args.last().cloned()
61    }
62}
63
64impl fmt::Display for FunctionArgs {
65    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
66        write!(f, "{}", join_vector(&self.args, ", ", false))
67    }
68}
69
70impl Prettier for FunctionArgs {
71    fn pretty(&self, level: usize, max: usize) -> String {
72        let mut v = vec![];
73        for ex in &self.args {
74            v.push(ex.pretty(level, max));
75        }
76        v.join(",\n")
77    }
78}
79
80/// Functions is a list of all functions supported by PromQL, including their types.
81#[derive(Debug, Clone, PartialEq, Eq)]
82#[cfg_attr(feature = "ser", derive(serde::Serialize))]
83#[cfg_attr(feature = "ser", serde(rename_all = "camelCase"))]
84pub struct Function {
85    pub name: &'static str,
86    pub arg_types: Vec<ValueType>,
87    #[cfg_attr(
88        feature = "ser",
89        serde(serialize_with = "Function::serialize_variadic")
90    )]
91    pub variadic: bool,
92    pub return_type: ValueType,
93}
94
95impl Function {
96    pub fn new(
97        name: &'static str,
98        arg_types: Vec<ValueType>,
99        variadic: bool,
100        return_type: ValueType,
101    ) -> Self {
102        Self {
103            name,
104            arg_types,
105            variadic,
106            return_type,
107        }
108    }
109
110    #[cfg(feature = "ser")]
111    pub(crate) fn serialize_variadic<S>(variadic: &bool, serializer: S) -> Result<S::Ok, S::Error>
112    where
113        S: serde::Serializer,
114    {
115        if *variadic {
116            serializer.serialize_i8(1)
117        } else {
118            serializer.serialize_i8(0)
119        }
120    }
121}
122
123macro_rules! map {
124    // if variadic args, then the last is the variadic one
125    ($(($name:literal, $arg:expr, $ret:expr)),*) => (
126        {
127            let mut m: HashMap<&'static str, Function> = HashMap::new();
128            $(
129                let variadic = FUNCTIONS_WITH_VARIADIC_ARGS.contains($name);
130                let func = Function::new($name, $arg, variadic, $ret);
131                m.insert($name, func);
132            )*
133            m
134        }
135    );
136}
137
138lazy_static! {
139    static ref FUNCTIONS_WITH_VARIADIC_ARGS: HashSet<&'static str> = HashSet::from([
140        "days_in_month",
141        "day_of_year",
142        "day_of_month",
143        "day_of_week",
144        "year",
145        "month",
146        "hour",
147        "minute",
148        "label_join",
149        "sort_by_label",
150        "sort_by_label_desc",
151        "round",
152    ]);
153    static ref FUNCTIONS: HashMap<&'static str, Function> = map!(
154        ("abs", vec![ValueType::Vector], ValueType::Vector),
155        ("absent", vec![ValueType::Vector], ValueType::Vector),
156        (
157            "absent_over_time",
158            vec![ValueType::Matrix],
159            ValueType::Vector
160        ),
161        ("acos", vec![ValueType::Vector], ValueType::Vector),
162        ("acosh", vec![ValueType::Vector], ValueType::Vector),
163        ("asin", vec![ValueType::Vector], ValueType::Vector),
164        ("asinh", vec![ValueType::Vector], ValueType::Vector),
165        ("atan", vec![ValueType::Vector], ValueType::Vector),
166        ("atanh", vec![ValueType::Vector], ValueType::Vector),
167        ("avg_over_time", vec![ValueType::Matrix], ValueType::Vector),
168        ("ceil", vec![ValueType::Vector], ValueType::Vector),
169        ("changes", vec![ValueType::Matrix], ValueType::Vector),
170        (
171            "clamp",
172            vec![ValueType::Vector, ValueType::Scalar, ValueType::Scalar],
173            ValueType::Vector
174        ),
175        (
176            "clamp_max",
177            vec![ValueType::Vector, ValueType::Scalar],
178            ValueType::Vector
179        ),
180        (
181            "clamp_min",
182            vec![ValueType::Vector, ValueType::Scalar],
183            ValueType::Vector
184        ),
185        ("cos", vec![ValueType::Vector], ValueType::Vector),
186        ("cosh", vec![ValueType::Vector], ValueType::Vector),
187        (
188            "count_over_time",
189            vec![ValueType::Matrix],
190            ValueType::Vector
191        ),
192        ("days_in_month", vec![ValueType::Vector], ValueType::Vector),
193        ("day_of_month", vec![ValueType::Vector], ValueType::Vector),
194        ("day_of_week", vec![ValueType::Vector], ValueType::Vector),
195        ("day_of_year", vec![ValueType::Vector], ValueType::Vector),
196        ("deg", vec![ValueType::Vector], ValueType::Vector),
197        ("delta", vec![ValueType::Matrix], ValueType::Vector),
198        ("deriv", vec![ValueType::Matrix], ValueType::Vector),
199        ("exp", vec![ValueType::Vector], ValueType::Vector),
200        ("floor", vec![ValueType::Vector], ValueType::Vector),
201        (
202            "histogram_count",
203            vec![ValueType::Vector],
204            ValueType::Vector
205        ),
206        ("histogram_sum", vec![ValueType::Vector], ValueType::Vector),
207        ("histogram_avg", vec![ValueType::Vector], ValueType::Vector),
208        (
209            "histogram_fraction",
210            vec![ValueType::Scalar, ValueType::Scalar, ValueType::Vector],
211            ValueType::Vector
212        ),
213        (
214            "histogram_quantile",
215            vec![ValueType::Scalar, ValueType::Vector],
216            ValueType::Vector
217        ),
218        ("histogram_stddev", vec![ValueType::Vector], ValueType::Vector),
219        ("histogram_stdvar", vec![ValueType::Vector], ValueType::Vector),
220        (
221            "double_exponential_smoothing",
222            vec![ValueType::Matrix, ValueType::Scalar, ValueType::Scalar],
223            ValueType::Vector
224        ),
225        // Kept for backward compatibility; Prometheus 3.x renamed this function.
226        (
227            "holt_winters",
228            vec![ValueType::Matrix, ValueType::Scalar, ValueType::Scalar],
229            ValueType::Vector
230        ),
231        ("hour", vec![ValueType::Vector], ValueType::Vector),
232        ("idelta", vec![ValueType::Matrix], ValueType::Vector),
233        ("increase", vec![ValueType::Matrix], ValueType::Vector),
234        ("irate", vec![ValueType::Matrix], ValueType::Vector),
235        (
236            "label_replace",
237            vec![
238                ValueType::Vector,
239                ValueType::String,
240                ValueType::String,
241                ValueType::String,
242                ValueType::String,
243            ],
244            ValueType::Vector
245        ),
246        (
247            "label_join",
248            vec![
249                ValueType::Vector,
250                ValueType::String,
251                ValueType::String,
252                ValueType::String,
253            ],
254            ValueType::Vector
255        ),
256        ("last_over_time", vec![ValueType::Matrix], ValueType::Vector),
257        ("ln", vec![ValueType::Vector], ValueType::Vector),
258        ("log10", vec![ValueType::Vector], ValueType::Vector),
259        ("log2", vec![ValueType::Vector], ValueType::Vector),
260        ("max_over_time", vec![ValueType::Matrix], ValueType::Vector),
261        ("min_over_time", vec![ValueType::Matrix], ValueType::Vector),
262        ("minute", vec![ValueType::Vector], ValueType::Vector),
263        ("month", vec![ValueType::Vector], ValueType::Vector),
264        ("pi", vec![], ValueType::Scalar),
265        (
266            "predict_linear",
267            vec![ValueType::Matrix, ValueType::Scalar],
268            ValueType::Vector
269        ),
270        (
271            "present_over_time",
272            vec![ValueType::Matrix],
273            ValueType::Vector
274        ),
275        (
276            "quantile_over_time",
277            vec![ValueType::Scalar, ValueType::Matrix],
278            ValueType::Vector
279        ),
280        ("rad", vec![ValueType::Vector], ValueType::Vector),
281        ("rate", vec![ValueType::Matrix], ValueType::Vector),
282        ("resets", vec![ValueType::Matrix], ValueType::Vector),
283        (
284            "round",
285            vec![ValueType::Vector, ValueType::Scalar],
286            ValueType::Vector
287        ),
288        ("scalar", vec![ValueType::Vector], ValueType::Scalar),
289        ("sgn", vec![ValueType::Vector], ValueType::Vector),
290        ("sin", vec![ValueType::Vector], ValueType::Vector),
291        ("sinh", vec![ValueType::Vector], ValueType::Vector),
292        ("sort", vec![ValueType::Vector], ValueType::Vector),
293        ("sort_desc", vec![ValueType::Vector], ValueType::Vector),
294        (
295            "sort_by_label",
296            vec![ValueType::Vector, ValueType::String, ValueType::String],
297            ValueType::Vector
298        ),
299        (
300            "sort_by_label_desc",
301            vec![ValueType::Vector, ValueType::String, ValueType::String],
302            ValueType::Vector
303        ),
304        ("sqrt", vec![ValueType::Vector], ValueType::Vector),
305        (
306            "stddev_over_time",
307            vec![ValueType::Matrix],
308            ValueType::Vector
309        ),
310        (
311            "stdvar_over_time",
312            vec![ValueType::Matrix],
313            ValueType::Vector
314        ),
315        ("sum_over_time", vec![ValueType::Matrix], ValueType::Vector),
316        ("tan", vec![ValueType::Vector], ValueType::Vector),
317        ("tanh", vec![ValueType::Vector], ValueType::Vector),
318        ("time", vec![], ValueType::Scalar),
319        ("timestamp", vec![ValueType::Vector], ValueType::Vector),
320        ("vector", vec![ValueType::Scalar], ValueType::Vector),
321        ("year", vec![ValueType::Vector], ValueType::Vector)
322    );
323}
324
325/// get_function returns a predefined Function object for the given name.
326pub(crate) fn get_function(name: &str) -> Option<Function> {
327    FUNCTIONS.get(name).cloned()
328}
329
330#[cfg(test)]
331mod tests {
332    use super::*;
333    use crate::parser::*;
334
335    #[test]
336    fn test_function_equality() {
337        let func = "month";
338        assert!(get_function(func).is_some());
339        assert_eq!(get_function(func), get_function(func));
340    }
341
342    #[test]
343    fn test_function_args_equality() {
344        assert_eq!(FunctionArgs::empty_args(), FunctionArgs::empty_args());
345
346        let arg1 = Expr::NumberLiteral(NumberLiteral::new(1.0));
347        let arg2 = Expr::StringLiteral(StringLiteral {
348            val: "prometheus".into(),
349        });
350        let args1 = FunctionArgs::new_args(arg1).append_args(arg2);
351
352        let arg1 = Expr::NumberLiteral(NumberLiteral::new(0.5 + 0.5));
353        let arg2 = Expr::StringLiteral(StringLiteral {
354            val: String::from("prometheus"),
355        });
356        let args2 = FunctionArgs::new_args(arg1).append_args(arg2);
357
358        assert_eq!(args1, args2);
359    }
360
361    #[test]
362    fn test_args_display() {
363        let cases = vec![
364            (
365                FunctionArgs::new_args(Expr::from(VectorSelector::from("up"))),
366                "up",
367            ),
368            (
369                FunctionArgs::empty_args()
370                    .append_args(Expr::from("src1"))
371                    .append_args(Expr::from("src2"))
372                    .append_args(Expr::from("src3")),
373                r#""src1", "src2", "src3""#,
374            ),
375        ];
376
377        for (args, expect) in cases {
378            assert_eq!(expect, args.to_string())
379        }
380    }
381}