simple_test/parser/
ast.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 crate::label::{Labels, Matchers, METRIC_NAME};
16use crate::parser::token::{
17    self, token_display, T_BOTTOMK, T_COUNT_VALUES, T_END, T_QUANTILE, T_START, T_TOPK,
18};
19use crate::parser::token::{Token, TokenId, TokenType};
20use crate::parser::value::ValueType;
21use crate::parser::{indent, Function, FunctionArgs, Prettier, MAX_CHARACTERS_PER_LINE};
22use crate::util::display_duration;
23use std::fmt::{self, Write};
24use std::ops::{Deref, DerefMut, Neg};
25use std::sync::Arc;
26use std::time::{Duration, SystemTime};
27
28/// LabelModifier acts as
29///
30/// # Aggregation Modifier
31///
32/// - Exclude means `ignoring`
33/// - Include means `on`
34///
35/// # Vector Match Modifier
36///
37/// - Exclude means `without` removes the listed labels from the result vector,
38/// while all other labels are preserved in the output.
39/// - Include means `by` does the opposite and drops labels that are not listed in the by clause,
40/// even if their label values are identical between all elements of the vector.
41///
42/// if empty listed labels, meaning no grouping
43#[derive(Debug, Clone, PartialEq, Eq)]
44pub enum LabelModifier {
45    Include(Labels),
46    Exclude(Labels),
47}
48
49impl LabelModifier {
50    pub fn labels(&self) -> &Labels {
51        match self {
52            LabelModifier::Include(l) => l,
53            LabelModifier::Exclude(l) => l,
54        }
55    }
56
57    pub fn is_include(&self) -> bool {
58        matches!(*self, LabelModifier::Include(_))
59    }
60
61    pub fn include(ls: Vec<&str>) -> Self {
62        Self::Include(Labels::new(ls))
63    }
64
65    pub fn exclude(ls: Vec<&str>) -> Self {
66        Self::Exclude(Labels::new(ls))
67    }
68}
69
70/// The label list provided with the group_left or group_right modifier contains
71/// additional labels from the "one"-side to be included in the result metrics.
72#[derive(Debug, Clone, PartialEq, Eq)]
73pub enum VectorMatchCardinality {
74    OneToOne,
75    ManyToOne(Labels),
76    OneToMany(Labels),
77    ManyToMany, // logical/set binary operators
78}
79
80impl VectorMatchCardinality {
81    pub fn labels(&self) -> Option<&Labels> {
82        match self {
83            VectorMatchCardinality::ManyToOne(l) => Some(l),
84            VectorMatchCardinality::OneToMany(l) => Some(l),
85            VectorMatchCardinality::ManyToMany => None,
86            VectorMatchCardinality::OneToOne => None,
87        }
88    }
89
90    pub fn many_to_one(ls: Vec<&str>) -> Self {
91        Self::ManyToOne(Labels::new(ls))
92    }
93
94    pub fn one_to_many(ls: Vec<&str>) -> Self {
95        Self::OneToMany(Labels::new(ls))
96    }
97}
98
99/// Binary Expr Modifier
100#[derive(Debug, Clone, PartialEq, Eq)]
101pub struct BinModifier {
102    /// The matching behavior for the operation if both operands are Vectors.
103    /// If they are not this field is None.
104    pub card: VectorMatchCardinality,
105
106    /// on/ignoring on labels.
107    /// like a + b, no match modifier is needed.
108    pub matching: Option<LabelModifier>,
109    /// If a comparison operator, return 0/1 rather than filtering.
110    pub return_bool: bool,
111}
112
113impl fmt::Display for BinModifier {
114    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115        let mut s = String::from(self.bool_str());
116
117        if let Some(matching) = &self.matching {
118            match matching {
119                LabelModifier::Include(ls) => write!(s, "on ({ls}) ")?,
120                LabelModifier::Exclude(ls) if !ls.is_empty() => write!(s, "ignoring ({ls}) ")?,
121                _ => (),
122            }
123        }
124
125        match &self.card {
126            VectorMatchCardinality::ManyToOne(ls) => write!(s, "group_left ({ls}) ")?,
127            VectorMatchCardinality::OneToMany(ls) => write!(s, "group_right ({ls}) ")?,
128            _ => (),
129        }
130
131        if s.trim().is_empty() {
132            write!(f, "")
133        } else {
134            write!(f, " {}", s.trim_end()) // there is a leading space here
135        }
136    }
137}
138
139impl Default for BinModifier {
140    fn default() -> Self {
141        Self {
142            card: VectorMatchCardinality::OneToOne,
143            matching: None,
144            return_bool: false,
145        }
146    }
147}
148
149impl BinModifier {
150    pub fn with_card(mut self, card: VectorMatchCardinality) -> Self {
151        self.card = card;
152        self
153    }
154
155    pub fn with_matching(mut self, matching: Option<LabelModifier>) -> Self {
156        self.matching = matching;
157        self
158    }
159
160    pub fn with_return_bool(mut self, return_bool: bool) -> Self {
161        self.return_bool = return_bool;
162        self
163    }
164
165    pub fn is_labels_joint(&self) -> bool {
166        matches!(
167            (self.card.labels(), &self.matching),
168            (Some(labels), Some(matching)) if labels.is_joint(matching.labels())
169        )
170    }
171
172    pub fn intersect_labels(&self) -> Option<Vec<String>> {
173        if let Some(labels) = self.card.labels() {
174            if let Some(matching) = &self.matching {
175                return Some(labels.intersect(matching.labels()).labels);
176            }
177        };
178        None
179    }
180
181    pub fn is_matching_on(&self) -> bool {
182        matches!(&self.matching, Some(matching) if matching.is_include())
183    }
184
185    pub fn is_matching_labels_not_empty(&self) -> bool {
186        matches!(&self.matching, Some(matching) if !matching.labels().is_empty())
187    }
188
189    pub fn bool_str(&self) -> &str {
190        if self.return_bool {
191            "bool "
192        } else {
193            ""
194        }
195    }
196}
197
198#[derive(Debug, Clone, PartialEq, Eq)]
199pub enum Offset {
200    Pos(Duration),
201    Neg(Duration),
202}
203
204impl fmt::Display for Offset {
205    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206        match self {
207            Offset::Pos(dur) => write!(f, "{}", display_duration(dur)),
208            Offset::Neg(dur) => write!(f, "-{}", display_duration(dur)),
209        }
210    }
211}
212#[derive(Debug, Clone, PartialEq, Eq)]
213pub enum AtModifier {
214    Start,
215    End,
216    /// at can be earlier than UNIX_EPOCH
217    At(SystemTime),
218}
219
220impl fmt::Display for AtModifier {
221    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
222        match self {
223            AtModifier::Start => write!(f, "@ {}()", token_display(T_START)),
224            AtModifier::End => write!(f, "@ {}()", token_display(T_END)),
225            AtModifier::At(time) => {
226                let d = time
227                    .duration_since(SystemTime::UNIX_EPOCH)
228                    .unwrap_or(Duration::ZERO); // This should not happen
229                write!(f, "@ {:.3}", d.as_secs() as f64)
230            }
231        }
232    }
233}
234impl TryFrom<TokenId> for AtModifier {
235    type Error = String;
236
237    fn try_from(id: TokenId) -> Result<Self, Self::Error> {
238        match id {
239            T_START => Ok(AtModifier::Start),
240            T_END => Ok(AtModifier::End),
241            _ => Err(format!(
242                "invalid @ modifier preprocessor '{}', START or END is valid.",
243                token::token_display(id)
244            )),
245        }
246    }
247}
248
249impl TryFrom<Token> for AtModifier {
250    type Error = String;
251
252    fn try_from(token: Token) -> Result<Self, Self::Error> {
253        AtModifier::try_from(token.id())
254    }
255}
256
257impl TryFrom<NumberLiteral> for AtModifier {
258    type Error = String;
259
260    fn try_from(num: NumberLiteral) -> Result<Self, Self::Error> {
261        AtModifier::try_from(num.val)
262    }
263}
264
265impl TryFrom<Expr> for AtModifier {
266    type Error = String;
267
268    fn try_from(ex: Expr) -> Result<Self, Self::Error> {
269        match ex {
270            Expr::NumberLiteral(nl) => AtModifier::try_from(nl),
271            _ => Err("invalid float value after @ modifier".into()),
272        }
273    }
274}
275
276impl TryFrom<f64> for AtModifier {
277    type Error = String;
278
279    fn try_from(secs: f64) -> Result<Self, Self::Error> {
280        let err_info = format!("timestamp out of bounds for @ modifier: {secs}");
281
282        if secs.is_nan() || secs.is_infinite() || secs >= f64::MAX || secs <= f64::MIN {
283            return Err(err_info);
284        }
285        let milli = (secs * 1000f64).round().abs() as u64;
286
287        let duration = Duration::from_millis(milli);
288        let mut st = Some(SystemTime::UNIX_EPOCH);
289        if secs.is_sign_positive() {
290            st = SystemTime::UNIX_EPOCH.checked_add(duration);
291        }
292        if secs.is_sign_negative() {
293            st = SystemTime::UNIX_EPOCH.checked_sub(duration);
294        }
295
296        st.map(Self::At).ok_or(err_info)
297    }
298}
299
300/// EvalStmt holds an expression and information on the range it should
301/// be evaluated on.
302#[allow(rustdoc::broken_intra_doc_links)]
303#[derive(Debug, Clone)]
304pub struct EvalStmt {
305    /// Expression to be evaluated.
306    pub expr: Expr,
307
308    /// The time boundaries for the evaluation. If start equals end an instant
309    /// is evaluated.
310    pub start: SystemTime,
311    pub end: SystemTime,
312    /// Time between two evaluated instants for the range [start:end].
313    pub interval: Duration,
314    /// Lookback delta to use for this evaluation.
315    pub lookback_delta: Duration,
316}
317
318/// Grammar:
319/// ``` norust
320/// <aggr-op> [without|by (<label list>)] ([parameter,] <vector expression>)
321/// <aggr-op>([parameter,] <vector expression>) [without|by (<label list>)]
322/// ```
323///
324/// parameter is only required for `count_values`, `quantile`, `topk` and `bottomk`.
325#[derive(Debug, Clone, PartialEq, Eq)]
326pub struct AggregateExpr {
327    /// The used aggregation operation.
328    pub op: TokenType,
329    /// The Vector expression over which is aggregated.
330    pub expr: Box<Expr>,
331    /// Parameter used by some aggregators.
332    pub param: Option<Box<Expr>>,
333    /// modifier is optional for some aggregation operators, like sum.
334    pub modifier: Option<LabelModifier>,
335}
336
337impl AggregateExpr {
338    fn get_op_string(&self) -> String {
339        let mut s = self.op.to_string();
340
341        if let Some(modifier) = &self.modifier {
342            match modifier {
343                LabelModifier::Exclude(ls) => write!(s, " without ({ls}) ").unwrap(),
344                LabelModifier::Include(ls) if !ls.is_empty() => write!(s, " by ({ls}) ").unwrap(),
345                _ => (),
346            }
347        }
348        s
349    }
350}
351
352impl fmt::Display for AggregateExpr {
353    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
354        write!(f, "{}", self.get_op_string())?;
355
356        write!(f, "(")?;
357        if let Some(param) = &self.param {
358            write!(f, "{param}, ")?;
359        }
360        write!(f, "{})", self.expr)?;
361
362        Ok(())
363    }
364}
365
366impl Prettier for AggregateExpr {
367    fn format(&self, level: usize, max: usize) -> String {
368        let mut s = format!("{}{}(\n", indent(level), self.get_op_string());
369        if let Some(param) = &self.param {
370            writeln!(s, "{},", param.pretty(level + 1, max)).unwrap();
371        }
372        writeln!(s, "{}", self.expr.pretty(level + 1, max)).unwrap();
373        write!(s, "{})", indent(level)).unwrap();
374        s
375    }
376}
377
378/// UnaryExpr will negate the expr
379#[derive(Debug, Clone, PartialEq, Eq)]
380pub struct UnaryExpr {
381    pub expr: Box<Expr>,
382}
383
384impl fmt::Display for UnaryExpr {
385    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
386        write!(f, "-{}", self.expr)
387    }
388}
389
390impl Prettier for UnaryExpr {
391    fn pretty(&self, level: usize, max: usize) -> String {
392        format!(
393            "{}-{}",
394            indent(level),
395            self.expr.pretty(level, max).trim_start()
396        )
397    }
398}
399
400/// Grammar:
401/// ``` norust
402/// <vector expr> <bin-op> ignoring(<label list>) group_left(<label list>) <vector expr>
403/// <vector expr> <bin-op> ignoring(<label list>) group_right(<label list>) <vector expr>
404/// <vector expr> <bin-op> on(<label list>) group_left(<label list>) <vector expr>
405/// <vector expr> <bin-op> on(<label list>) group_right(<label list>) <vector expr>
406/// ```
407#[derive(Debug, Clone, PartialEq, Eq)]
408pub struct BinaryExpr {
409    /// The operation of the expression.
410    pub op: TokenType,
411    /// The operands on the left sides of the operator.
412    pub lhs: Box<Expr>,
413    /// The operands on the right sides of the operator.
414    pub rhs: Box<Expr>,
415
416    pub modifier: Option<BinModifier>,
417}
418
419impl BinaryExpr {
420    pub fn is_matching_on(&self) -> bool {
421        matches!(&self.modifier, Some(modifier) if modifier.is_matching_on())
422    }
423
424    pub fn is_matching_labels_not_empty(&self) -> bool {
425        matches!(&self.modifier, Some(modifier) if modifier.is_matching_labels_not_empty())
426    }
427
428    pub fn return_bool(&self) -> bool {
429        matches!(&self.modifier, Some(modifier) if modifier.return_bool)
430    }
431
432    /// check if labels of card and matching are joint
433    pub fn is_labels_joint(&self) -> bool {
434        matches!(&self.modifier, Some(modifier) if modifier.is_labels_joint())
435    }
436
437    /// intersect labels of card and matching
438    pub fn intersect_labels(&self) -> Option<Vec<String>> {
439        self.modifier
440            .as_ref()
441            .and_then(|modifier| modifier.intersect_labels())
442    }
443
444    fn get_op_matching_string(&self) -> String {
445        match &self.modifier {
446            Some(modifier) => format!("{}{modifier}", self.op),
447            None => self.op.to_string(),
448        }
449    }
450}
451
452impl fmt::Display for BinaryExpr {
453    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
454        write!(
455            f,
456            "{} {} {}",
457            self.lhs,
458            self.get_op_matching_string(),
459            self.rhs
460        )
461    }
462}
463
464impl Prettier for BinaryExpr {
465    fn format(&self, level: usize, max: usize) -> String {
466        format!(
467            "{}\n{}{}\n{}",
468            self.lhs.pretty(level + 1, max),
469            indent(level),
470            self.get_op_matching_string(),
471            self.rhs.pretty(level + 1, max)
472        )
473    }
474}
475
476#[derive(Debug, Clone, PartialEq, Eq)]
477pub struct ParenExpr {
478    pub expr: Box<Expr>,
479}
480
481impl fmt::Display for ParenExpr {
482    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
483        write!(f, "({})", self.expr)
484    }
485}
486
487impl Prettier for ParenExpr {
488    fn format(&self, level: usize, max: usize) -> String {
489        format!(
490            "{}(\n{}\n{})",
491            indent(level),
492            self.expr.pretty(level + 1, max),
493            indent(level)
494        )
495    }
496}
497
498/// Grammar:
499/// ```norust
500/// <instant_query> '[' <range> ':' [<resolution>] ']' [ @ <float_literal> ] [ offset <duration> ]
501/// ```
502#[derive(Debug, Clone, PartialEq, Eq)]
503pub struct SubqueryExpr {
504    pub expr: Box<Expr>,
505    pub offset: Option<Offset>,
506    pub at: Option<AtModifier>,
507    pub range: Duration,
508    /// Default is the global evaluation interval.
509    pub step: Option<Duration>,
510}
511
512impl SubqueryExpr {
513    fn get_time_suffix_string(&self) -> String {
514        let step = match &self.step {
515            Some(step) => display_duration(step),
516            None => String::from(""),
517        };
518        let range = display_duration(&self.range);
519
520        let mut s = format!("[{range}:{step}]");
521
522        if let Some(at) = &self.at {
523            write!(s, " {at}").unwrap();
524        }
525
526        if let Some(offset) = &self.offset {
527            write!(s, " offset {offset}").unwrap();
528        }
529        s
530    }
531}
532
533impl fmt::Display for SubqueryExpr {
534    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
535        write!(f, "{}{}", self.expr, self.get_time_suffix_string())
536    }
537}
538
539impl Prettier for SubqueryExpr {
540    fn pretty(&self, level: usize, max: usize) -> String {
541        format!(
542            "{}{}",
543            self.expr.pretty(level, max),
544            self.get_time_suffix_string()
545        )
546    }
547}
548
549#[derive(Debug, Clone)]
550pub struct NumberLiteral {
551    pub val: f64,
552}
553
554impl NumberLiteral {
555    pub fn new(val: f64) -> Self {
556        Self { val }
557    }
558}
559
560impl PartialEq for NumberLiteral {
561    fn eq(&self, other: &Self) -> bool {
562        self.val == other.val || self.val.is_nan() && other.val.is_nan()
563    }
564}
565
566impl Eq for NumberLiteral {}
567
568impl Neg for NumberLiteral {
569    type Output = Self;
570
571    fn neg(self) -> Self::Output {
572        NumberLiteral { val: -self.val }
573    }
574}
575
576impl fmt::Display for NumberLiteral {
577    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
578        if self.val == f64::INFINITY {
579            write!(f, "Inf")
580        } else if self.val == f64::NEG_INFINITY {
581            write!(f, "-Inf")
582        } else if f64::is_nan(self.val) {
583            write!(f, "NaN")
584        } else {
585            write!(f, "{}", self.val)
586        }
587    }
588}
589
590impl Prettier for NumberLiteral {
591    fn needs_split(&self, _max: usize) -> bool {
592        false
593    }
594}
595
596#[derive(Debug, Clone, PartialEq, Eq)]
597pub struct StringLiteral {
598    pub val: String,
599}
600
601impl fmt::Display for StringLiteral {
602    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
603        write!(f, "\"{}\"", self.val)
604    }
605}
606
607impl Prettier for StringLiteral {
608    fn needs_split(&self, _max: usize) -> bool {
609        false
610    }
611}
612
613#[derive(Debug, Clone, PartialEq, Eq)]
614pub struct VectorSelector {
615    pub name: Option<String>,
616    pub matchers: Matchers,
617    pub offset: Option<Offset>,
618    pub at: Option<AtModifier>,
619}
620
621impl Deref for VectorSelector {
622    type Target = ();
623
624    fn deref(&self) -> &Self::Target {
625        todo!()
626    }
627}
628
629impl DerefMut for VectorSelector {
630    fn deref_mut(&mut self) -> &mut Self::Target {
631        todo!()
632    }
633}
634
635impl VectorSelector {
636    pub fn new(name: Option<String>, matchers: Matchers) -> Self {
637        VectorSelector {
638            name,
639            matchers,
640            offset: None,
641            at: None,
642        }
643    }
644}
645
646impl Default for VectorSelector {
647    fn default() -> Self {
648        Self {
649            name: None,
650            matchers: Matchers::empty(),
651            offset: None,
652            at: None,
653        }
654    }
655}
656
657impl From<String> for VectorSelector {
658    fn from(name: String) -> Self {
659        VectorSelector {
660            name: Some(name),
661            offset: None,
662            at: None,
663            matchers: Matchers::empty(),
664        }
665    }
666}
667
668/// directly create an instant vector with only METRIC_NAME matcher.
669///
670/// # Examples
671///
672/// Basic usage:
673///
674/// ``` rust
675/// use promql_parser::label::Matchers;
676/// use promql_parser::parser::VectorSelector;
677///
678/// let vs = VectorSelector {
679///     name: Some(String::from("foo")),
680///     offset: None,
681///     at: None,
682///     matchers: Matchers::empty(),
683/// };
684///
685/// assert_eq!(VectorSelector::from("foo"), vs);
686/// ```
687impl From<&str> for VectorSelector {
688    fn from(name: &str) -> Self {
689        VectorSelector::from(name.to_string())
690    }
691}
692
693impl Neg for VectorSelector {
694    type Output = UnaryExpr;
695
696    fn neg(self) -> Self::Output {
697        let ex = Expr::VectorSelector(self);
698        UnaryExpr { expr: Box::new(ex) }
699    }
700}
701
702impl fmt::Display for VectorSelector {
703    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
704        if let Some(name) = &self.name {
705            write!(f, "{name}")?;
706        }
707        let matchers = &self.matchers.to_string();
708        if !matchers.is_empty() {
709            write!(f, "{{{matchers}}}")?;
710        }
711        if let Some(at) = &self.at {
712            write!(f, " {at}")?;
713        }
714        if let Some(offset) = &self.offset {
715            write!(f, " offset {offset}")?;
716        }
717        Ok(())
718    }
719}
720
721impl Prettier for VectorSelector {
722    fn needs_split(&self, _max: usize) -> bool {
723        false
724    }
725}
726
727#[derive(Debug, Clone, PartialEq, Eq)]
728pub struct MatrixSelector {
729    pub vs: VectorSelector,
730    pub range: Duration,
731}
732
733impl fmt::Display for MatrixSelector {
734    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
735        if let Some(name) = &self.vs.name {
736            write!(f, "{name}")?;
737        }
738
739        let matchers = &self.vs.matchers.to_string();
740        if !matchers.is_empty() {
741            write!(f, "{{{matchers}}}")?;
742        }
743
744        write!(f, "[{}]", display_duration(&self.range))?;
745
746        if let Some(at) = &self.vs.at {
747            write!(f, " {at}")?;
748        }
749
750        if let Some(offset) = &self.vs.offset {
751            write!(f, " offset {offset}")?;
752        }
753
754        Ok(())
755    }
756}
757
758impl Prettier for MatrixSelector {
759    fn needs_split(&self, _max: usize) -> bool {
760        false
761    }
762}
763
764/// Call represents Prometheus Function.
765/// Some functions have special cases:
766///
767/// ## exp
768///
769/// exp(v instant-vector) calculates the exponential function for all elements in v.
770/// Special cases are:
771///
772/// ```promql
773/// Exp(+Inf) = +Inf
774/// Exp(NaN) = NaN
775/// ```
776///
777/// ## ln
778///
779/// ln(v instant-vector) calculates the natural logarithm for all elements in v.
780/// Special cases are:
781///
782/// ```promql
783/// ln(+Inf) = +Inf
784/// ln(0) = -Inf
785/// ln(x < 0) = NaN
786/// ln(NaN) = NaN
787/// ```
788///
789/// TODO: support more special cases of function call
790///
791///  - acos()
792///  - acosh()
793///  - asin()
794///  - asinh()
795///  - atan()
796///  - atanh()
797///  - cos()
798///  - cosh()
799///  - sin()
800///  - sinh()
801///  - tan()
802///  - tanh()
803#[derive(Debug, Clone, PartialEq, Eq)]
804pub struct Call {
805    pub func: Function,
806    pub args: FunctionArgs,
807}
808
809impl fmt::Display for Call {
810    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
811        write!(f, "{}({})", self.func.name, self.args)
812    }
813}
814
815impl Prettier for Call {
816    fn format(&self, level: usize, max: usize) -> String {
817        format!(
818            "{}{}(\n{}\n{})",
819            indent(level),
820            self.func.name,
821            self.args.pretty(level + 1, max),
822            indent(level)
823        )
824    }
825}
826
827/// Node for extending the AST. [Extension] won't be generate by this parser itself.
828#[derive(Debug, Clone)]
829pub struct Extension {
830    pub expr: Arc<dyn ExtensionExpr>,
831}
832
833/// The interface for extending the AST with custom expression node.
834pub trait ExtensionExpr: std::fmt::Debug + Send + Sync {
835    fn as_any(&self) -> &dyn std::any::Any;
836
837    fn name(&self) -> &str;
838
839    fn value_type(&self) -> ValueType;
840
841    fn children(&self) -> &[Expr];
842}
843
844impl PartialEq for Extension {
845    fn eq(&self, other: &Self) -> bool {
846        format!("{:?}", self) == format!("{:?}", other)
847    }
848}
849
850impl Eq for Extension {}
851
852#[derive(Debug, Clone, PartialEq, Eq)]
853pub enum Expr {
854    /// Aggregate represents an aggregation operation on a Vector.
855    Aggregate(AggregateExpr),
856
857    /// Unary represents a unary operation on another expression.
858    /// Currently unary operations are only supported for Scalars.
859    Unary(UnaryExpr),
860
861    /// Binary represents a binary expression between two child expressions.
862    Binary(BinaryExpr),
863
864    /// Paren wraps an expression so it cannot be disassembled as a consequence
865    /// of operator precedence.
866    Paren(ParenExpr),
867
868    /// SubqueryExpr represents a subquery.
869    Subquery(SubqueryExpr),
870
871    /// NumberLiteral represents a number.
872    NumberLiteral(NumberLiteral),
873
874    /// StringLiteral represents a string.
875    StringLiteral(StringLiteral),
876
877    /// VectorSelector represents a Vector selection.
878    VectorSelector(VectorSelector),
879
880    /// MatrixSelector represents a Matrix selection.
881    MatrixSelector(MatrixSelector),
882
883    /// Call represents a function call.
884    Call(Call),
885
886    /// Extension represents an extension expression. It is for user to attach additional
887    /// information to the AST. This parser won't generate Extension node.
888    Extension(Extension),
889}
890
891impl Expr {
892    pub(crate) fn new_vector_selector(
893        name: Option<String>,
894        matchers: Matchers,
895    ) -> Result<Self, String> {
896        let vs = VectorSelector::new(name, matchers);
897        Ok(Self::VectorSelector(vs))
898    }
899
900    pub(crate) fn new_unary_expr(expr: Expr) -> Result<Self, String> {
901        match expr {
902            Expr::StringLiteral(_) => Err("unary expression only allowed on expressions of type scalar or vector, got: string".into()),
903            Expr::MatrixSelector(_) => Err("unary expression only allowed on expressions of type scalar or vector, got: matrix".into()),
904            _ => Ok(-expr),
905        }
906    }
907
908    pub(crate) fn new_subquery_expr(
909        expr: Expr,
910        range: Duration,
911        step: Option<Duration>,
912    ) -> Result<Self, String> {
913        let se = Expr::Subquery(SubqueryExpr {
914            expr: Box::new(expr),
915            offset: None,
916            at: None,
917            range,
918            step,
919        });
920        Ok(se)
921    }
922
923    pub(crate) fn new_paren_expr(expr: Expr) -> Result<Self, String> {
924        let ex = Expr::Paren(ParenExpr {
925            expr: Box::new(expr),
926        });
927        Ok(ex)
928    }
929
930    /// NOTE: @ and offset is not set here.
931    pub(crate) fn new_matrix_selector(expr: Expr, range: Duration) -> Result<Self, String> {
932        match expr {
933            Expr::VectorSelector(VectorSelector {
934                offset: Some(_), ..
935            }) => Err("no offset modifiers allowed before range".into()),
936            Expr::VectorSelector(VectorSelector { at: Some(_), .. }) => {
937                Err("no @ modifiers allowed before range".into())
938            }
939            Expr::VectorSelector(vs) => {
940                let ms = Expr::MatrixSelector(MatrixSelector { vs, range });
941                Ok(ms)
942            }
943            _ => Err("ranges only allowed for vector selectors".into()),
944        }
945    }
946
947    pub(crate) fn at_expr(self, at: AtModifier) -> Result<Self, String> {
948        let already_set_err = Err("@ <timestamp> may not be set multiple times".into());
949        match self {
950            Expr::VectorSelector(mut vs) => match vs.at {
951                None => {
952                    vs.at = Some(at);
953                    Ok(Expr::VectorSelector(vs))
954                }
955                Some(_) => already_set_err,
956            },
957            Expr::MatrixSelector(mut ms) => match ms.vs.at {
958                None => {
959                    ms.vs.at = Some(at);
960                    Ok(Expr::MatrixSelector(ms))
961                }
962                Some(_) => already_set_err,
963            },
964            Expr::Subquery(mut s) => match s.at {
965                None => {
966                    s.at = Some(at);
967                    Ok(Expr::Subquery(s))
968                }
969                Some(_) => already_set_err,
970            },
971            _ => {
972                Err("@ modifier must be preceded by an vector selector or matrix selector or a subquery".into())
973            }
974        }
975    }
976
977    /// set offset field for specified Expr, but CAN ONLY be set once.
978    pub(crate) fn offset_expr(self, offset: Offset) -> Result<Self, String> {
979        let already_set_err = Err("offset may not be set multiple times".into());
980        match self {
981            Expr::VectorSelector(mut vs) => match vs.offset {
982                None => {
983                    vs.offset = Some(offset);
984                    Ok(Expr::VectorSelector(vs))
985                }
986                Some(_) => already_set_err,
987            },
988            Expr::MatrixSelector(mut ms) => match ms.vs.offset {
989                None => {
990                    ms.vs.offset = Some(offset);
991                    Ok(Expr::MatrixSelector(ms))
992                }
993                Some(_) => already_set_err,
994            },
995            Expr::Subquery(mut s) => match s.offset {
996                None => {
997                    s.offset = Some(offset);
998                    Ok(Expr::Subquery(s))
999                }
1000                Some(_) => already_set_err,
1001            },
1002            _ => {
1003                Err("offset modifier must be preceded by an vector selector or matrix selector or a subquery".into())
1004            }
1005        }
1006    }
1007
1008    pub(crate) fn new_call(func: Function, args: FunctionArgs) -> Result<Expr, String> {
1009        Ok(Expr::Call(Call { func, args }))
1010    }
1011
1012    pub(crate) fn new_binary_expr(
1013        lhs: Expr,
1014        op: TokenId,
1015        modifier: Option<BinModifier>,
1016        rhs: Expr,
1017    ) -> Result<Expr, String> {
1018        let ex = BinaryExpr {
1019            op: TokenType::new(op),
1020            lhs: Box::new(lhs),
1021            rhs: Box::new(rhs),
1022            modifier,
1023        };
1024        Ok(Expr::Binary(ex))
1025    }
1026
1027    pub(crate) fn new_aggregate_expr(
1028        op: TokenId,
1029        modifier: Option<LabelModifier>,
1030        args: FunctionArgs,
1031    ) -> Result<Expr, String> {
1032        let op = TokenType::new(op);
1033        if args.is_empty() {
1034            return Err(format!(
1035                "no arguments for aggregate expression '{op}' provided"
1036            ));
1037        }
1038        let mut desired_args_count = 1;
1039        let mut param = None;
1040        if op.is_aggregator_with_param() {
1041            desired_args_count = 2;
1042            param = args.first();
1043        }
1044        if args.len() != desired_args_count {
1045            return Err(format!(
1046                "wrong number of arguments for aggregate expression provided, expected {}, got {}",
1047                desired_args_count,
1048                args.len()
1049            ));
1050        }
1051
1052        match args.last() {
1053            Some(expr) => Ok(Expr::Aggregate(AggregateExpr {
1054                op,
1055                expr,
1056                param,
1057                modifier,
1058            })),
1059            None => Err(
1060                "aggregate operation needs a single instant vector parameter, but found none"
1061                    .into(),
1062            ),
1063        }
1064    }
1065
1066    pub fn value_type(&self) -> ValueType {
1067        match self {
1068            Expr::Aggregate(_) => ValueType::Vector,
1069            Expr::Unary(ex) => ex.expr.value_type(),
1070            Expr::Binary(ex) => {
1071                if ex.lhs.value_type() == ValueType::Scalar
1072                    && ex.rhs.value_type() == ValueType::Scalar
1073                {
1074                    ValueType::Scalar
1075                } else {
1076                    ValueType::Vector
1077                }
1078            }
1079            Expr::Paren(ex) => ex.expr.value_type(),
1080            Expr::Subquery(_) => ValueType::Matrix,
1081            Expr::NumberLiteral(_) => ValueType::Scalar,
1082            Expr::StringLiteral(_) => ValueType::String,
1083            Expr::VectorSelector(_) => ValueType::Vector,
1084            Expr::MatrixSelector(_) => ValueType::Matrix,
1085            Expr::Call(ex) => ex.func.return_type,
1086            Expr::Extension(ex) => ex.expr.value_type(),
1087        }
1088    }
1089
1090    /// only Some if expr is [Expr::NumberLiteral]
1091    pub(crate) fn scalar_value(&self) -> Option<f64> {
1092        match self {
1093            Expr::NumberLiteral(nl) => Some(nl.val),
1094            _ => None,
1095        }
1096    }
1097
1098    pub fn prettify(&self) -> String {
1099        self.pretty(0, MAX_CHARACTERS_PER_LINE)
1100    }
1101}
1102
1103impl From<String> for Expr {
1104    fn from(val: String) -> Self {
1105        Expr::StringLiteral(StringLiteral { val })
1106    }
1107}
1108
1109impl From<&str> for Expr {
1110    fn from(s: &str) -> Self {
1111        Expr::StringLiteral(StringLiteral { val: s.into() })
1112    }
1113}
1114
1115impl From<f64> for Expr {
1116    fn from(val: f64) -> Self {
1117        Expr::NumberLiteral(NumberLiteral { val })
1118    }
1119}
1120
1121/// directly create an Expr::VectorSelector from instant vector
1122///
1123/// # Examples
1124///
1125/// Basic usage:
1126///
1127/// ``` rust
1128/// use promql_parser::label::Matchers;
1129/// use promql_parser::parser::{Expr, VectorSelector};
1130///
1131/// let name = String::from("foo");
1132/// let vs = VectorSelector::new(Some(name), Matchers::empty());
1133///
1134/// assert_eq!(Expr::VectorSelector(vs), Expr::from(VectorSelector::from("foo")));
1135/// ```
1136impl From<VectorSelector> for Expr {
1137    fn from(vs: VectorSelector) -> Self {
1138        Expr::VectorSelector(vs)
1139    }
1140}
1141
1142impl Neg for Expr {
1143    type Output = Self;
1144
1145    fn neg(self) -> Self::Output {
1146        match self {
1147            Expr::NumberLiteral(nl) => Expr::NumberLiteral(-nl),
1148            _ => Expr::Unary(UnaryExpr {
1149                expr: Box::new(self),
1150            }),
1151        }
1152    }
1153}
1154
1155impl fmt::Display for Expr {
1156    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1157        match self {
1158            Expr::Aggregate(ex) => write!(f, "{ex}"),
1159            Expr::Unary(ex) => write!(f, "{ex}"),
1160            Expr::Binary(ex) => write!(f, "{ex}"),
1161            Expr::Paren(ex) => write!(f, "{ex}"),
1162            Expr::Subquery(ex) => write!(f, "{ex}"),
1163            Expr::NumberLiteral(ex) => write!(f, "{ex}"),
1164            Expr::StringLiteral(ex) => write!(f, "{ex}"),
1165            Expr::VectorSelector(ex) => write!(f, "{ex}"),
1166            Expr::MatrixSelector(ex) => write!(f, "{ex}"),
1167            Expr::Call(ex) => write!(f, "{ex}"),
1168            Expr::Extension(ext) => write!(f, "{ext:?}"),
1169        }
1170    }
1171}
1172
1173impl Prettier for Expr {
1174    fn pretty(&self, level: usize, max: usize) -> String {
1175        match self {
1176            Expr::Aggregate(ex) => ex.pretty(level, max),
1177            Expr::Unary(ex) => ex.pretty(level, max),
1178            Expr::Binary(ex) => ex.pretty(level, max),
1179            Expr::Paren(ex) => ex.pretty(level, max),
1180            Expr::Subquery(ex) => ex.pretty(level, max),
1181            Expr::NumberLiteral(ex) => ex.pretty(level, max),
1182            Expr::StringLiteral(ex) => ex.pretty(level, max),
1183            Expr::VectorSelector(ex) => ex.pretty(level, max),
1184            Expr::MatrixSelector(ex) => ex.pretty(level, max),
1185            Expr::Call(ex) => ex.pretty(level, max),
1186            Expr::Extension(ext) => format!("{ext:?}"),
1187        }
1188    }
1189}
1190
1191/// check_ast checks the validity of the provided AST. This includes type checking.
1192/// Recursively check correct typing for child nodes and raise errors in case of bad typing.
1193pub(crate) fn check_ast(expr: Expr) -> Result<Expr, String> {
1194    match expr {
1195        Expr::Binary(ex) => check_ast_for_binary_expr(ex),
1196        Expr::Aggregate(ex) => check_ast_for_aggregate_expr(ex),
1197        Expr::Call(ex) => check_ast_for_call(ex),
1198        Expr::Unary(ex) => check_ast_for_unary(ex),
1199        Expr::Subquery(ex) => check_ast_for_subquery(ex),
1200        Expr::VectorSelector(ex) => check_ast_for_vector_selector(ex),
1201        Expr::Paren(_) => Ok(expr),
1202        Expr::NumberLiteral(_) => Ok(expr),
1203        Expr::StringLiteral(_) => Ok(expr),
1204        Expr::MatrixSelector(_) => Ok(expr),
1205        Expr::Extension(_) => Ok(expr),
1206    }
1207}
1208
1209fn expect_type(
1210    expected: ValueType,
1211    actual: Option<ValueType>,
1212    context: &str,
1213) -> Result<bool, String> {
1214    match actual {
1215        Some(actual) => {
1216            if actual == expected {
1217                Ok(true)
1218            } else {
1219                Err(format!(
1220                    "expected type {expected} in {context}, got {actual}"
1221                ))
1222            }
1223        }
1224        None => Err(format!("expected type {expected} in {context}, got None")),
1225    }
1226}
1227
1228/// the original logic is redundant in prometheus, and the following coding blocks
1229/// have been optimized for readability, but all logic SHOULD be covered.
1230fn check_ast_for_binary_expr(mut ex: BinaryExpr) -> Result<Expr, String> {
1231    if !ex.op.is_operator() {
1232        return Err(format!(
1233            "binary expression does not support operator '{}'",
1234            ex.op
1235        ));
1236    }
1237
1238    if ex.return_bool() && !ex.op.is_comparison_operator() {
1239        return Err("bool modifier can only be used on comparison operators".into());
1240    }
1241
1242    if ex.op.is_comparison_operator()
1243        && ex.lhs.value_type() == ValueType::Scalar
1244        && ex.rhs.value_type() == ValueType::Scalar
1245        && !ex.return_bool()
1246    {
1247        return Err("comparisons between scalars must use BOOL modifier".into());
1248    }
1249
1250    // For `on` matching, a label can only appear in one of the lists.
1251    // Every time series of the result vector must be uniquely identifiable.
1252    if ex.is_matching_on() && ex.is_labels_joint() {
1253        if let Some(labels) = ex.intersect_labels() {
1254            if let Some(label) = labels.first() {
1255                return Err(format!(
1256                    "label '{label}' must not occur in ON and GROUP clause at once"
1257                ));
1258            }
1259        };
1260    }
1261
1262    if ex.op.is_set_operator() {
1263        if ex.lhs.value_type() == ValueType::Scalar || ex.rhs.value_type() == ValueType::Scalar {
1264            return Err(format!(
1265                "set operator '{}' not allowed in binary scalar expression",
1266                ex.op
1267            ));
1268        }
1269
1270        if ex.lhs.value_type() == ValueType::Vector && ex.rhs.value_type() == ValueType::Vector {
1271            if let Some(ref modifier) = ex.modifier {
1272                if matches!(modifier.card, VectorMatchCardinality::OneToMany(_))
1273                    || matches!(modifier.card, VectorMatchCardinality::ManyToOne(_))
1274                {
1275                    return Err(format!("no grouping allowed for '{}' operation", ex.op));
1276                }
1277            };
1278        }
1279
1280        match &mut ex.modifier {
1281            Some(modifier) => {
1282                if modifier.card == VectorMatchCardinality::OneToOne {
1283                    modifier.card = VectorMatchCardinality::ManyToMany;
1284                }
1285            }
1286            None => {
1287                ex.modifier =
1288                    Some(BinModifier::default().with_card(VectorMatchCardinality::ManyToMany));
1289            }
1290        }
1291    }
1292
1293    if ex.lhs.value_type() != ValueType::Scalar && ex.lhs.value_type() != ValueType::Vector {
1294        return Err("binary expression must contain only scalar and instant vector types".into());
1295    }
1296    if ex.rhs.value_type() != ValueType::Scalar && ex.rhs.value_type() != ValueType::Vector {
1297        return Err("binary expression must contain only scalar and instant vector types".into());
1298    }
1299
1300    if (ex.lhs.value_type() != ValueType::Vector || ex.rhs.value_type() != ValueType::Vector)
1301        && ex.is_matching_labels_not_empty()
1302    {
1303        return Err("vector matching only allowed between vectors".into());
1304    }
1305
1306    Ok(Expr::Binary(ex))
1307}
1308
1309fn check_ast_for_aggregate_expr(ex: AggregateExpr) -> Result<Expr, String> {
1310    if !ex.op.is_aggregator() {
1311        return Err(format!(
1312            "aggregation operator expected in aggregation expression but got '{}'",
1313            ex.op
1314        ));
1315    }
1316
1317    expect_type(
1318        ValueType::Vector,
1319        Some(ex.expr.value_type()),
1320        "aggregation expression",
1321    )?;
1322
1323    if matches!(ex.op.id(), T_TOPK | T_BOTTOMK | T_QUANTILE) {
1324        expect_type(
1325            ValueType::Scalar,
1326            ex.param.as_ref().map(|ex| ex.value_type()),
1327            "aggregation expression",
1328        )?;
1329    }
1330
1331    if ex.op.id() == T_COUNT_VALUES {
1332        expect_type(
1333            ValueType::String,
1334            ex.param.as_ref().map(|ex| ex.value_type()),
1335            "aggregation expression",
1336        )?;
1337    }
1338
1339    Ok(Expr::Aggregate(ex))
1340}
1341
1342fn check_ast_for_call(ex: Call) -> Result<Expr, String> {
1343    let expected_args_len = ex.func.arg_types.len();
1344    let name = ex.func.name;
1345    let actual_args_len = ex.args.len();
1346
1347    if ex.func.variadic {
1348        let expected_args_len_without_default = expected_args_len - 1;
1349        if expected_args_len_without_default > actual_args_len {
1350            return Err(format!(
1351                "expected at least {expected_args_len_without_default} argument(s) in call to '{name}', got {actual_args_len}"
1352            ));
1353        }
1354
1355        // `label_join` do not have a maximum arguments threshold.
1356        // this hard code SHOULD be careful if new functions are supported by Prometheus.
1357        if actual_args_len > expected_args_len && name.ne("label_join") {
1358            return Err(format!(
1359                "expected at most {expected_args_len} argument(s) in call to '{name}', got {actual_args_len}"
1360            ));
1361        }
1362    }
1363
1364    if !ex.func.variadic && expected_args_len != actual_args_len {
1365        return Err(format!(
1366            "expected {expected_args_len} argument(s) in call to '{name}', got {actual_args_len}"
1367        ));
1368    }
1369
1370    // special cases from https://prometheus.io/docs/prometheus/latest/querying/functions
1371    if name.eq("exp") {
1372        if let Some(val) = ex.args.first().and_then(|ex| ex.scalar_value()) {
1373            if val.is_nan() || val.is_infinite() {
1374                return Ok(Expr::Call(ex));
1375            }
1376        }
1377    } else if name.eq("ln") || name.eq("log2") || name.eq("log10") {
1378        if let Some(val) = ex.args.first().and_then(|ex| ex.scalar_value()) {
1379            if val.is_nan() || val.is_infinite() || val <= 0.0 {
1380                return Ok(Expr::Call(ex));
1381            }
1382        }
1383    }
1384
1385    for (mut idx, actual_arg) in ex.args.args.iter().enumerate() {
1386        // this only happens when function args are variadic
1387        if idx >= ex.func.arg_types.len() {
1388            idx = ex.func.arg_types.len() - 1;
1389        }
1390
1391        expect_type(
1392            ex.func.arg_types[idx],
1393            Some(actual_arg.value_type()),
1394            &format!("call to function '{name}'"),
1395        )?;
1396    }
1397
1398    Ok(Expr::Call(ex))
1399}
1400
1401fn check_ast_for_unary(ex: UnaryExpr) -> Result<Expr, String> {
1402    let value_type = ex.expr.value_type();
1403    if value_type != ValueType::Scalar && value_type != ValueType::Vector {
1404        return Err(format!(
1405            "unary expression only allowed on expressions of type scalar or vector, got {value_type}"
1406        ));
1407    }
1408
1409    Ok(Expr::Unary(ex))
1410}
1411
1412fn check_ast_for_subquery(ex: SubqueryExpr) -> Result<Expr, String> {
1413    let value_type = ex.expr.value_type();
1414    if value_type != ValueType::Vector {
1415        return Err(format!(
1416            "subquery is only allowed on vector, got {value_type} instead"
1417        ));
1418    }
1419
1420    Ok(Expr::Subquery(ex))
1421}
1422
1423fn check_ast_for_vector_selector(ex: VectorSelector) -> Result<Expr, String> {
1424    match ex.name {
1425        Some(ref name) => match ex.matchers.find_matcher_value(METRIC_NAME) {
1426            Some(val) => Err(format!(
1427                "metric name must not be set twice: '{}' or '{}'",
1428                name, val
1429            )),
1430            None => Ok(Expr::VectorSelector(ex)),
1431        },
1432        None if ex.matchers.is_empty_matchers() => {
1433            // When name is None, a vector selector must contain at least one non-empty matcher
1434            // to prevent implicit selection of all metrics (e.g. by a typo).
1435            Err("vector selector must contain at least one non-empty matcher".into())
1436        }
1437        _ => Ok(Expr::VectorSelector(ex)),
1438    }
1439}
1440
1441#[cfg(test)]
1442mod tests {
1443    use super::*;
1444    use crate::label::{MatchOp, Matcher};
1445
1446    #[test]
1447    fn test_valid_at_modifier() {
1448        let cases = vec![
1449            // tuple: (seconds, elapsed milliseconds before or after UNIX_EPOCH)
1450            (0.0, 0),
1451            (1000.3, 1000300),    // after UNIX_EPOCH
1452            (1000.9, 1000900),    // after UNIX_EPOCH
1453            (1000.9991, 1000999), // after UNIX_EPOCH
1454            (1000.9999, 1001000), // after UNIX_EPOCH
1455            (-1000.3, 1000300),   // before UNIX_EPOCH
1456            (-1000.9, 1000900),   // before UNIX_EPOCH
1457        ];
1458
1459        for (secs, elapsed) in cases {
1460            match AtModifier::try_from(secs).unwrap() {
1461                AtModifier::At(st) => {
1462                    if secs.is_sign_positive() || secs == 0.0 {
1463                        assert_eq!(
1464                            elapsed,
1465                            st.duration_since(SystemTime::UNIX_EPOCH)
1466                                .unwrap()
1467                                .as_millis()
1468                        )
1469                    } else if secs.is_sign_negative() {
1470                        assert_eq!(
1471                            elapsed,
1472                            SystemTime::UNIX_EPOCH
1473                                .duration_since(st)
1474                                .unwrap()
1475                                .as_millis()
1476                        )
1477                    }
1478                }
1479                _ => panic!(),
1480            }
1481        }
1482
1483        assert_eq!(
1484            AtModifier::try_from(Expr::from(1.0)),
1485            AtModifier::try_from(1.0),
1486        );
1487    }
1488
1489    #[test]
1490    fn test_invalid_at_modifier() {
1491        let cases = vec![
1492            f64::MAX,
1493            f64::MIN,
1494            f64::NAN,
1495            f64::INFINITY,
1496            f64::NEG_INFINITY,
1497        ];
1498
1499        for secs in cases {
1500            assert!(AtModifier::try_from(secs).is_err())
1501        }
1502
1503        assert_eq!(
1504            AtModifier::try_from(token::T_ADD),
1505            Err("invalid @ modifier preprocessor '+', START or END is valid.".into())
1506        );
1507
1508        assert_eq!(
1509            AtModifier::try_from(Expr::from("string literal")),
1510            Err("invalid float value after @ modifier".into())
1511        );
1512    }
1513
1514    #[test]
1515    fn test_binary_labels() {
1516        assert_eq!(
1517            &Labels::new(vec!["foo", "bar"]),
1518            LabelModifier::Include(Labels::new(vec!["foo", "bar"])).labels()
1519        );
1520
1521        assert_eq!(
1522            &Labels::new(vec!["foo", "bar"]),
1523            LabelModifier::Exclude(Labels::new(vec!["foo", "bar"])).labels()
1524        );
1525
1526        assert_eq!(
1527            &Labels::new(vec!["foo", "bar"]),
1528            VectorMatchCardinality::OneToMany(Labels::new(vec!["foo", "bar"]))
1529                .labels()
1530                .unwrap()
1531        );
1532
1533        assert_eq!(
1534            &Labels::new(vec!["foo", "bar"]),
1535            VectorMatchCardinality::ManyToOne(Labels::new(vec!["foo", "bar"]))
1536                .labels()
1537                .unwrap()
1538        );
1539
1540        assert_eq!(VectorMatchCardinality::OneToOne.labels(), None);
1541        assert_eq!(VectorMatchCardinality::ManyToMany.labels(), None);
1542    }
1543
1544    #[test]
1545    fn test_neg() {
1546        assert_eq!(
1547            -VectorSelector::from("foo"),
1548            UnaryExpr {
1549                expr: Box::new(Expr::from(VectorSelector::from("foo")))
1550            }
1551        )
1552    }
1553
1554    #[test]
1555    fn test_scalar_value() {
1556        assert_eq!(Some(1.0), Expr::from(1.0).scalar_value());
1557        assert_eq!(None, Expr::from("1.0").scalar_value());
1558    }
1559
1560    #[test]
1561    fn test_at_expr() {
1562        assert_eq!(
1563            "@ <timestamp> may not be set multiple times",
1564            Expr::from(VectorSelector::from("foo"))
1565                .at_expr(AtModifier::try_from(1.0).unwrap())
1566                .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1567                .unwrap_err()
1568        );
1569
1570        assert_eq!(
1571            "@ <timestamp> may not be set multiple times",
1572            Expr::new_matrix_selector(
1573                Expr::from(VectorSelector::from("foo")),
1574                Duration::from_secs(1),
1575            )
1576            .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1577            .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1578            .unwrap_err()
1579        );
1580
1581        assert_eq!(
1582            "@ <timestamp> may not be set multiple times",
1583            Expr::new_subquery_expr(
1584                Expr::from(VectorSelector::from("foo")),
1585                Duration::from_secs(1),
1586                None,
1587            )
1588            .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1589            .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1590            .unwrap_err()
1591        )
1592    }
1593
1594    #[test]
1595    fn test_offset_expr() {
1596        assert_eq!(
1597            "offset may not be set multiple times",
1598            Expr::from(VectorSelector::from("foo"))
1599                .offset_expr(Offset::Pos(Duration::from_secs(1000)))
1600                .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1601                .unwrap_err()
1602        );
1603
1604        assert_eq!(
1605            "offset may not be set multiple times",
1606            Expr::new_matrix_selector(
1607                Expr::from(VectorSelector::from("foo")),
1608                Duration::from_secs(1),
1609            )
1610            .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1611            .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1612            .unwrap_err()
1613        );
1614
1615        assert_eq!(
1616            "offset may not be set multiple times",
1617            Expr::new_subquery_expr(
1618                Expr::from(VectorSelector::from("foo")),
1619                Duration::from_secs(1),
1620                None,
1621            )
1622            .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1623            .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1624            .unwrap_err()
1625        );
1626    }
1627
1628    #[test]
1629    fn test_expr_to_string() {
1630        let mut cases = vec![
1631            ("1", "1"),
1632            ("- 1", "-1"),
1633            ("+ 1", "1"),
1634            ("Inf", "Inf"),
1635            ("inf", "Inf"),
1636            ("+Inf", "Inf"),
1637            ("- Inf", "-Inf"),
1638            (".5", "0.5"),
1639            ("5.", "5"),
1640            ("123.4567", "123.4567"),
1641            ("5e-3", "0.005"),
1642            ("5e3", "5000"),
1643            ("0xc", "12"),
1644            ("0755", "493"),
1645            ("08", "8"),
1646            ("+5.5e-3", "0.0055"),
1647            ("-0755", "-493"),
1648            ("NaN", "NaN"),
1649            ("NAN", "NaN"),
1650            ("- 1^2", "-1 ^ 2"),
1651            ("+1 + -2 * 1", "1 + -2 * 1"),
1652            ("1 + 2/(3*1)", "1 + 2 / (3 * 1)"),
1653            ("foo*sum", "foo * sum"),
1654            ("foo * on(test,blub) bar", "foo * on (test, blub) bar"),
1655            (
1656                r#"up{job="hi", instance="in"} offset 5m @ 100"#,
1657                r#"up{instance="in",job="hi"} @ 100.000 offset 5m"#,
1658            ),
1659            (
1660                r#"up{job="hi", instance="in"}"#,
1661                r#"up{instance="in",job="hi"}"#,
1662            ),
1663            ("sum (up) by (job,instance)", "sum by (job, instance) (up)"),
1664            (
1665                "foo / on(test,blub) group_left(bar) bar",
1666                "foo / on (test, blub) group_left (bar) bar",
1667            ),
1668            (
1669                "foo / on(test,blub) group_right(bar) bar",
1670                "foo / on (test, blub) group_right (bar) bar",
1671            ),
1672            (
1673                r#"foo{a="b",foo!="bar",test=~"test",bar!~"baz"}"#,
1674                r#"foo{a="b",bar!~"baz",foo!="bar",test=~"test"}"#,
1675            ),
1676            (
1677                r#"{__name__=~"foo.+",__name__=~".*bar"}"#,
1678                r#"{__name__=~".*bar",__name__=~"foo.+"}"#,
1679            ),
1680            (
1681                r#"test{a="b"}[5y] OFFSET 3d"#,
1682                r#"test{a="b"}[5y] offset 3d"#,
1683            ),
1684            (
1685                r#"{a="b"}[5y] OFFSET 3d"#,
1686                r#"{a="b"}[5y] offset 3d"#,
1687            ),
1688            (
1689                "sum(some_metric) without(and, by, avg, count, alert, annotations)",
1690                "sum without (and, by, avg, count, alert, annotations) (some_metric)",
1691            ),
1692            (
1693                r#"floor(some_metric{foo!="bar"})"#,
1694                r#"floor(some_metric{foo!="bar"})"#,
1695            ),
1696            (
1697                "sum(rate(http_request_duration_seconds[10m])) / count(rate(http_request_duration_seconds[10m]))",
1698                "sum(rate(http_request_duration_seconds[10m])) / count(rate(http_request_duration_seconds[10m]))",
1699            ),
1700            ("rate(some_metric[5m])", "rate(some_metric[5m])"),
1701            ("round(some_metric,5)", "round(some_metric, 5)"),
1702            (
1703                r#"absent(sum(nonexistent{job="myjob"}))"#,
1704                r#"absent(sum(nonexistent{job="myjob"}))"#,
1705            ),
1706            (
1707                "histogram_quantile(0.9,rate(http_request_duration_seconds_bucket[10m]))",
1708                "histogram_quantile(0.9, rate(http_request_duration_seconds_bucket[10m]))",
1709            ),
1710            (
1711                "histogram_quantile(0.9,sum(rate(http_request_duration_seconds_bucket[10m])) by(job,le))",
1712                "histogram_quantile(0.9, sum by (job, le) (rate(http_request_duration_seconds_bucket[10m])))",
1713            ),
1714            (
1715                r#"label_join(up{job="api-server",src1="a",src2="b",src3="c"}, "foo", ",", "src1", "src2", "src3")"#,
1716                r#"label_join(up{job="api-server",src1="a",src2="b",src3="c"}, "foo", ",", "src1", "src2", "src3")"#,
1717            ),
1718            (
1719                r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s] @ 100"#,
1720                r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s] @ 100.000"#,
1721            ),
1722            (
1723                r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s]"#,
1724                r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s]"#,
1725            ),
1726            (
1727                r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] offset 4m)[4m:3s]"#,
1728                r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] offset 4m)[4m:3s]"#,
1729            ),
1730            ("some_metric OFFSET 1m [10m:5s]", "some_metric offset 1m[10m:5s]"),
1731            ("some_metric @123 [10m:5s]", "some_metric @ 123.000[10m:5s]")
1732        ];
1733
1734        // the following cases are from https://github.com/prometheus/prometheus/blob/main/promql/parser/printer_test.go
1735        let mut cases1 = vec![
1736            (
1737                r#"sum by() (task:errors:rate10s{job="s"})"#,
1738                r#"sum(task:errors:rate10s{job="s"})"#,
1739            ),
1740            (
1741                r#"sum by(code) (task:errors:rate10s{job="s"})"#,
1742                r#"sum by (code) (task:errors:rate10s{job="s"})"#,
1743            ),
1744            (
1745                r#"sum without() (task:errors:rate10s{job="s"})"#,
1746                r#"sum without () (task:errors:rate10s{job="s"})"#,
1747            ),
1748            (
1749                r#"sum without(instance) (task:errors:rate10s{job="s"})"#,
1750                r#"sum without (instance) (task:errors:rate10s{job="s"})"#,
1751            ),
1752            (
1753                r#"topk(5, task:errors:rate10s{job="s"})"#,
1754                r#"topk(5, task:errors:rate10s{job="s"})"#,
1755            ),
1756            (
1757                r#"count_values("value", task:errors:rate10s{job="s"})"#,
1758                r#"count_values("value", task:errors:rate10s{job="s"})"#,
1759            ),
1760            ("a - on() c", "a - on () c"),
1761            ("a - on(b) c", "a - on (b) c"),
1762            ("a - on(b) group_left(x) c", "a - on (b) group_left (x) c"),
1763            (
1764                "a - on(b) group_left(x, y) c",
1765                "a - on (b) group_left (x, y) c",
1766            ),
1767            ("a - on(b) group_left c", "a - on (b) group_left () c"),
1768            ("a - ignoring(b) c", "a - ignoring (b) c"),
1769            ("a - ignoring() c", "a - c"),
1770            ("up > bool 0", "up > bool 0"),
1771            ("a offset 1m", "a offset 1m"),
1772            ("a offset -7m", "a offset -7m"),
1773            (r#"a{c="d"}[5m] offset 1m"#, r#"a{c="d"}[5m] offset 1m"#),
1774            ("a[5m] offset 1m", "a[5m] offset 1m"),
1775            ("a[12m] offset -3m", "a[12m] offset -3m"),
1776            ("a[1h:5m] offset 1m", "a[1h:5m] offset 1m"),
1777            (r#"{__name__="a"}"#, r#"{__name__="a"}"#),
1778            (r#"a{b!="c"}[1m]"#, r#"a{b!="c"}[1m]"#),
1779            (r#"a{b=~"c"}[1m]"#, r#"a{b=~"c"}[1m]"#),
1780            (r#"a{b!~"c"}[1m]"#, r#"a{b!~"c"}[1m]"#),
1781            ("a @ 10", "a @ 10.000"),
1782            ("a[1m] @ 10", "a[1m] @ 10.000"),
1783            ("a @ start()", "a @ start()"),
1784            ("a @ end()", "a @ end()"),
1785            ("a[1m] @ start()", "a[1m] @ start()"),
1786            ("a[1m] @ end()", "a[1m] @ end()"),
1787        ];
1788
1789        cases.append(&mut cases1);
1790        for (input, expected) in cases {
1791            let expr = crate::parser::parse(input).unwrap();
1792            assert_eq!(expected, expr.to_string())
1793        }
1794    }
1795
1796    #[test]
1797    fn test_vector_selector_to_string() {
1798        let cases = vec![
1799            (VectorSelector::default(), ""),
1800            (VectorSelector::from("foobar"), "foobar"),
1801            (
1802                {
1803                    let name = Some(String::from("foobar"));
1804                    let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "a", "x"));
1805                    VectorSelector::new(name, matchers)
1806                },
1807                r#"foobar{a="x"}"#,
1808            ),
1809            (
1810                {
1811                    let matchers = Matchers::new(vec![
1812                        Matcher::new(MatchOp::Equal, "a", "x"),
1813                        Matcher::new(MatchOp::Equal, "b", "y"),
1814                    ]);
1815                    VectorSelector::new(None, matchers)
1816                },
1817                r#"{a="x",b="y"}"#,
1818            ),
1819            (
1820                {
1821                    let matchers =
1822                        Matchers::one(Matcher::new(MatchOp::Equal, METRIC_NAME, "foobar"));
1823                    VectorSelector::new(None, matchers)
1824                },
1825                r#"{__name__="foobar"}"#,
1826            ),
1827        ];
1828
1829        for (vs, expect) in cases {
1830            assert_eq!(expect, vs.to_string())
1831        }
1832    }
1833
1834    #[test]
1835    fn test_aggregate_expr_pretty() {
1836        let cases = vec![
1837            ("sum(foo)", "sum(foo)"),
1838            (
1839                r#"sum by() (task:errors:rate10s{job="s"})"#,
1840                r#"sum(
1841  task:errors:rate10s{job="s"}
1842)"#,
1843            ),
1844            (
1845                r#"sum without(job,foo) (task:errors:rate10s{job="s"})"#,
1846                r#"sum without (job, foo) (
1847  task:errors:rate10s{job="s"}
1848)"#,
1849            ),
1850            (
1851                r#"sum(task:errors:rate10s{job="s"}) without(job,foo)"#,
1852                r#"sum without (job, foo) (
1853  task:errors:rate10s{job="s"}
1854)"#,
1855            ),
1856            (
1857                r#"sum by(job,foo) (task:errors:rate10s{job="s"})"#,
1858                r#"sum by (job, foo) (
1859  task:errors:rate10s{job="s"}
1860)"#,
1861            ),
1862            (
1863                r#"sum (task:errors:rate10s{job="s"}) by(job,foo)"#,
1864                r#"sum by (job, foo) (
1865  task:errors:rate10s{job="s"}
1866)"#,
1867            ),
1868            (
1869                r#"topk(10, ask:errors:rate10s{job="s"})"#,
1870                r#"topk(
1871  10,
1872  ask:errors:rate10s{job="s"}
1873)"#,
1874            ),
1875            (
1876                r#"sum by(job,foo) (sum by(job,foo) (task:errors:rate10s{job="s"}))"#,
1877                r#"sum by (job, foo) (
1878  sum by (job, foo) (
1879    task:errors:rate10s{job="s"}
1880  )
1881)"#,
1882            ),
1883            (
1884                r#"sum by(job,foo) (sum by(job,foo) (sum by(job,foo) (task:errors:rate10s{job="s"})))"#,
1885                r#"sum by (job, foo) (
1886  sum by (job, foo) (
1887    sum by (job, foo) (
1888      task:errors:rate10s{job="s"}
1889    )
1890  )
1891)"#,
1892            ),
1893            (
1894                r#"sum by(job,foo)
1895(sum by(job,foo) (task:errors:rate10s{job="s"}))"#,
1896                r#"sum by (job, foo) (
1897  sum by (job, foo) (
1898    task:errors:rate10s{job="s"}
1899  )
1900)"#,
1901            ),
1902            (
1903                r#"sum by(job,foo)
1904(sum(task:errors:rate10s{job="s"}) without(job,foo))"#,
1905                r#"sum by (job, foo) (
1906  sum without (job, foo) (
1907    task:errors:rate10s{job="s"}
1908  )
1909)"#,
1910            ),
1911            (
1912                r#"sum by(job,foo) # Comment 1.
1913(sum by(job,foo) ( # Comment 2.
1914task:errors:rate10s{job="s"}))"#,
1915                r#"sum by (job, foo) (
1916  sum by (job, foo) (
1917    task:errors:rate10s{job="s"}
1918  )
1919)"#,
1920            ),
1921        ];
1922
1923        for (input, expect) in cases {
1924            let expr = crate::parser::parse(input);
1925            assert_eq!(expect, expr.unwrap().pretty(0, 10));
1926        }
1927    }
1928
1929    #[test]
1930    fn test_binary_expr_pretty() {
1931        let cases = vec![
1932            ("a+b", "a + b"),
1933            (
1934                "a == bool 1",
1935                "  a
1936== bool
1937  1",
1938            ),
1939            (
1940                "a == 1024000",
1941                "  a
1942==
1943  1024000",
1944            ),
1945            (
1946                "a + ignoring(job) b",
1947                "  a
1948+ ignoring (job)
1949  b",
1950            ),
1951            (
1952                "foo_1 + foo_2",
1953                "  foo_1
1954+
1955  foo_2",
1956            ),
1957            (
1958                "foo_1 + foo_2 + foo_3",
1959                "    foo_1
1960  +
1961    foo_2
1962+
1963  foo_3",
1964            ),
1965            (
1966                "foo + baar + foo_3",
1967                "  foo + baar
1968+
1969  foo_3",
1970            ),
1971            (
1972                "foo_1 + foo_2 + foo_3 + foo_4",
1973                "      foo_1
1974    +
1975      foo_2
1976  +
1977    foo_3
1978+
1979  foo_4",
1980            ),
1981            (
1982                "foo_1 + ignoring(foo) foo_2 + ignoring(job) group_left foo_3 + on(instance) group_right foo_4",
1983
1984                 "      foo_1
1985    + ignoring (foo)
1986      foo_2
1987  + ignoring (job) group_left ()
1988    foo_3
1989+ on (instance) group_right ()
1990  foo_4",
1991            ),
1992        ];
1993
1994        for (input, expect) in cases {
1995            let expr = crate::parser::parse(input);
1996            assert_eq!(expect, expr.unwrap().pretty(0, 10));
1997        }
1998    }
1999
2000    #[test]
2001    fn test_call_expr_pretty() {
2002        let cases = vec![
2003            (
2004                "rate(foo[1m])",
2005                "rate(
2006  foo[1m]
2007)",
2008            ),
2009            (
2010                "sum_over_time(foo[1m])",
2011                "sum_over_time(
2012  foo[1m]
2013)",
2014            ),
2015            (
2016                "rate(long_vector_selector[10m:1m] @ start() offset 1m)",
2017                "rate(
2018  long_vector_selector[10m:1m] @ start() offset 1m
2019)",
2020            ),
2021            (
2022                "histogram_quantile(0.9, rate(foo[1m]))",
2023                "histogram_quantile(
2024  0.9,
2025  rate(
2026    foo[1m]
2027  )
2028)",
2029            ),
2030            (
2031                "histogram_quantile(0.9, rate(foo[1m] @ start()))",
2032                "histogram_quantile(
2033  0.9,
2034  rate(
2035    foo[1m] @ start()
2036  )
2037)",
2038            ),
2039            (
2040                "max_over_time(rate(demo_api_request_duration_seconds_count[1m])[1m:] @ start() offset 1m)",
2041                "max_over_time(
2042  rate(
2043    demo_api_request_duration_seconds_count[1m]
2044  )[1m:] @ start() offset 1m
2045)",
2046            ),
2047            (
2048                r#"label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*")"#,
2049                r#"label_replace(
2050  up{job="api-server",service="a:c"},
2051  "foo",
2052  "$1",
2053  "service",
2054  "(.*):.*"
2055)"#,
2056            ),
2057            (
2058                r#"label_replace(label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*"), "foo", "$1", "service", "(.*):.*")"#,
2059                r#"label_replace(
2060  label_replace(
2061    up{job="api-server",service="a:c"},
2062    "foo",
2063    "$1",
2064    "service",
2065    "(.*):.*"
2066  ),
2067  "foo",
2068  "$1",
2069  "service",
2070  "(.*):.*"
2071)"#,
2072            ),
2073        ];
2074
2075        for (input, expect) in cases {
2076            let expr = crate::parser::parse(input);
2077            assert_eq!(expect, expr.unwrap().pretty(0, 10));
2078        }
2079    }
2080
2081    #[test]
2082    fn test_paren_expr_pretty() {
2083        let cases = vec![
2084            ("(foo)", "(foo)"),
2085            (
2086                "(_foo_long_)",
2087                "(
2088  _foo_long_
2089)",
2090            ),
2091            (
2092                "((foo_long))",
2093                "(
2094  (foo_long)
2095)",
2096            ),
2097            (
2098                "((_foo_long_))",
2099                "(
2100  (
2101    _foo_long_
2102  )
2103)",
2104            ),
2105            (
2106                "(((foo_long)))",
2107                "(
2108  (
2109    (foo_long)
2110  )
2111)",
2112            ),
2113            ("(1 + 2)", "(1 + 2)"),
2114            (
2115                "(foo + bar)",
2116                "(
2117  foo + bar
2118)",
2119            ),
2120            (
2121                "(foo_long + bar_long)",
2122                "(
2123    foo_long
2124  +
2125    bar_long
2126)",
2127            ),
2128            (
2129                "(foo_long + bar_long + bar_2_long)",
2130                "(
2131      foo_long
2132    +
2133      bar_long
2134  +
2135    bar_2_long
2136)",
2137            ),
2138            (
2139                "((foo_long + bar_long) + bar_2_long)",
2140                "(
2141    (
2142        foo_long
2143      +
2144        bar_long
2145    )
2146  +
2147    bar_2_long
2148)",
2149            ),
2150            (
2151                "(1111 + 2222)",
2152                "(
2153    1111
2154  +
2155    2222
2156)",
2157            ),
2158            (
2159                "(sum_over_time(foo[1m]))",
2160                "(
2161  sum_over_time(
2162    foo[1m]
2163  )
2164)",
2165            ),
2166            (
2167                r#"(label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*"))"#,
2168                r#"(
2169  label_replace(
2170    up{job="api-server",service="a:c"},
2171    "foo",
2172    "$1",
2173    "service",
2174    "(.*):.*"
2175  )
2176)"#,
2177            ),
2178            (
2179                r#"(label_replace(label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*"), "foo", "$1", "service", "(.*):.*"))"#,
2180                r#"(
2181  label_replace(
2182    label_replace(
2183      up{job="api-server",service="a:c"},
2184      "foo",
2185      "$1",
2186      "service",
2187      "(.*):.*"
2188    ),
2189    "foo",
2190    "$1",
2191    "service",
2192    "(.*):.*"
2193  )
2194)"#,
2195            ),
2196            (
2197                r#"(label_replace(label_replace((up{job="api-server",service="a:c"}), "foo", "$1", "service", "(.*):.*"), "foo", "$1", "service", "(.*):.*"))"#,
2198                r#"(
2199  label_replace(
2200    label_replace(
2201      (
2202        up{job="api-server",service="a:c"}
2203      ),
2204      "foo",
2205      "$1",
2206      "service",
2207      "(.*):.*"
2208    ),
2209    "foo",
2210    "$1",
2211    "service",
2212    "(.*):.*"
2213  )
2214)"#,
2215            ),
2216        ];
2217
2218        for (input, expect) in cases {
2219            let expr = crate::parser::parse(input);
2220            assert_eq!(expect, expr.unwrap().pretty(0, 10));
2221        }
2222    }
2223
2224    #[test]
2225    fn test_unary_expr_pretty() {
2226        let cases = vec![
2227            ("-1", "-1"),
2228            ("-vector_selector", "-vector_selector"),
2229            (
2230                "(-vector_selector)",
2231                "(
2232  -vector_selector
2233)",
2234            ),
2235            (
2236                "-histogram_quantile(0.9,rate(foo[1m]))",
2237                "-histogram_quantile(
2238  0.9,
2239  rate(
2240    foo[1m]
2241  )
2242)",
2243            ),
2244            (
2245                "-histogram_quantile(0.99, sum by (le) (rate(foo[1m])))",
2246                "-histogram_quantile(
2247  0.99,
2248  sum by (le) (
2249    rate(
2250      foo[1m]
2251    )
2252  )
2253)",
2254            ),
2255            (
2256                "-histogram_quantile(0.9, -rate(foo[1m] @ start()))",
2257                "-histogram_quantile(
2258  0.9,
2259  -rate(
2260    foo[1m] @ start()
2261  )
2262)",
2263            ),
2264            (
2265                "(-histogram_quantile(0.9, -rate(foo[1m] @ start())))",
2266                "(
2267  -histogram_quantile(
2268    0.9,
2269    -rate(
2270      foo[1m] @ start()
2271    )
2272  )
2273)",
2274            ),
2275        ];
2276
2277        for (input, expect) in cases {
2278            let expr = crate::parser::parse(input);
2279            assert_eq!(expect, expr.unwrap().pretty(0, 10));
2280        }
2281    }
2282
2283    #[test]
2284    fn test_expr_pretty() {
2285        // Following queries have been taken from https://monitoring.mixins.dev/
2286        let cases = vec![
2287            (
2288                r#"(node_filesystem_avail_bytes{job="node",fstype!=""} / node_filesystem_size_bytes{job="node",fstype!=""} * 100 < 40 and predict_linear(node_filesystem_avail_bytes{job="node",fstype!=""}[6h], 24*60*60) < 0 and node_filesystem_readonly{job="node",fstype!=""} == 0)"#,
2289                r#"(
2290            node_filesystem_avail_bytes{fstype!="",job="node"}
2291          /
2292            node_filesystem_size_bytes{fstype!="",job="node"}
2293        *
2294          100
2295      <
2296        40
2297    and
2298        predict_linear(
2299          node_filesystem_avail_bytes{fstype!="",job="node"}[6h],
2300            24 * 60
2301          *
2302            60
2303        )
2304      <
2305        0
2306  and
2307      node_filesystem_readonly{fstype!="",job="node"}
2308    ==
2309      0
2310)"#,
2311            ),
2312            (
2313                r#"(node_filesystem_avail_bytes{job="node",fstype!=""} / node_filesystem_size_bytes{job="node",fstype!=""} * 100 < 20 and predict_linear(node_filesystem_avail_bytes{job="node",fstype!=""}[6h], 4*60*60) < 0 and node_filesystem_readonly{job="node",fstype!=""} == 0)"#,
2314                r#"(
2315            node_filesystem_avail_bytes{fstype!="",job="node"}
2316          /
2317            node_filesystem_size_bytes{fstype!="",job="node"}
2318        *
2319          100
2320      <
2321        20
2322    and
2323        predict_linear(
2324          node_filesystem_avail_bytes{fstype!="",job="node"}[6h],
2325            4 * 60
2326          *
2327            60
2328        )
2329      <
2330        0
2331  and
2332      node_filesystem_readonly{fstype!="",job="node"}
2333    ==
2334      0
2335)"#,
2336            ),
2337            (
2338                r#"(node_timex_offset_seconds > 0.05 and deriv(node_timex_offset_seconds[5m]) >= 0) or (node_timex_offset_seconds < -0.05 and deriv(node_timex_offset_seconds[5m]) <= 0)"#,
2339                r#"  (
2340        node_timex_offset_seconds
2341      >
2342        0.05
2343    and
2344        deriv(
2345          node_timex_offset_seconds[5m]
2346        )
2347      >=
2348        0
2349  )
2350or
2351  (
2352        node_timex_offset_seconds
2353      <
2354        -0.05
2355    and
2356        deriv(
2357          node_timex_offset_seconds[5m]
2358        )
2359      <=
2360        0
2361  )"#,
2362            ),
2363            (
2364                r#"1 - ((node_memory_MemAvailable_bytes{job="node"} or (node_memory_Buffers_bytes{job="node"} + node_memory_Cached_bytes{job="node"} + node_memory_MemFree_bytes{job="node"} + node_memory_Slab_bytes{job="node"}) ) / node_memory_MemTotal_bytes{job="node"})"#,
2365                r#"  1
2366-
2367  (
2368      (
2369          node_memory_MemAvailable_bytes{job="node"}
2370        or
2371          (
2372                  node_memory_Buffers_bytes{job="node"}
2373                +
2374                  node_memory_Cached_bytes{job="node"}
2375              +
2376                node_memory_MemFree_bytes{job="node"}
2377            +
2378              node_memory_Slab_bytes{job="node"}
2379          )
2380      )
2381    /
2382      node_memory_MemTotal_bytes{job="node"}
2383  )"#,
2384            ),
2385            (
2386                r#"min by (job, integration) (rate(alertmanager_notifications_failed_total{job="alertmanager", integration=~".*"}[5m]) / rate(alertmanager_notifications_total{job="alertmanager", integration="~.*"}[5m])) > 0.01"#,
2387                r#"  min by (job, integration) (
2388      rate(
2389        alertmanager_notifications_failed_total{integration=~".*",job="alertmanager"}[5m]
2390      )
2391    /
2392      rate(
2393        alertmanager_notifications_total{integration="~.*",job="alertmanager"}[5m]
2394      )
2395  )
2396>
2397  0.01"#,
2398            ),
2399            (
2400                r#"(count by (job) (changes(process_start_time_seconds{job="alertmanager"}[10m]) > 4) / count by (job) (up{job="alertmanager"})) >= 0.5"#,
2401                r#"  (
2402      count by (job) (
2403          changes(
2404            process_start_time_seconds{job="alertmanager"}[10m]
2405          )
2406        >
2407          4
2408      )
2409    /
2410      count by (job) (
2411        up{job="alertmanager"}
2412      )
2413  )
2414>=
2415  0.5"#,
2416            ),
2417        ];
2418
2419        for (input, expect) in cases {
2420            let expr = crate::parser::parse(input);
2421            assert_eq!(expect, expr.unwrap().pretty(0, 10));
2422        }
2423    }
2424
2425    #[test]
2426    fn test_step_invariant_pretty() {
2427        let cases = vec![
2428            ("a @ 1", "a @ 1.000"),
2429            ("a @ start()", "a @ start()"),
2430            ("vector_selector @ start()", "vector_selector @ start()"),
2431        ];
2432
2433        for (input, expect) in cases {
2434            let expr = crate::parser::parse(input);
2435            assert_eq!(expect, expr.unwrap().pretty(0, 10));
2436        }
2437    }
2438
2439    #[test]
2440    fn test_prettify() {
2441        let cases = vec![
2442            ("vector_selector", "vector_selector"),
2443            (
2444                r#"vector_selector{fooooooooooooooooo="barrrrrrrrrrrrrrrrrrr",barrrrrrrrrrrrrrrrrrr="fooooooooooooooooo",process_name="alertmanager"}"#,
2445                r#"vector_selector{barrrrrrrrrrrrrrrrrrr="fooooooooooooooooo",fooooooooooooooooo="barrrrrrrrrrrrrrrrrrr",process_name="alertmanager"}"#,
2446            ),
2447            (
2448                r#"matrix_selector{fooooooooooooooooo="barrrrrrrrrrrrrrrrrrr",barrrrrrrrrrrrrrrrrrr="fooooooooooooooooo",process_name="alertmanager"}[1y2w3d]"#,
2449                r#"matrix_selector{barrrrrrrrrrrrrrrrrrr="fooooooooooooooooo",fooooooooooooooooo="barrrrrrrrrrrrrrrrrrr",process_name="alertmanager"}[382d]"#,
2450            ),
2451        ];
2452
2453        for (input, expect) in cases {
2454            assert_eq!(expect, crate::parser::parse(input).unwrap().prettify());
2455        }
2456    }
2457}