diff --git a/build.rs b/build.rs index 0390e51..8e3442c 100644 --- a/build.rs +++ b/build.rs @@ -17,10 +17,10 @@ use lrlex::{ct_token_map, DefaultLexerTypes}; use lrpar::CTParserBuilder; fn main() -> Result<(), Box> { - let ctp = CTParserBuilder::>::new() + let ctp = CTParserBuilder::>::new() .yacckind(YaccKind::Grmtools) .recoverer(lrpar::RecoveryKind::None) .grammar_in_src_dir("parser/promql.y")? .build()?; - ct_token_map::("token_map", ctp.token_map(), None) + ct_token_map::("token_map", ctp.token_map(), None) } diff --git a/src/parser/ast.rs b/src/parser/ast.rs index 8b1a296..1f8e8db 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -100,8 +100,38 @@ impl VectorMatchCardinality { } } +/// VectorMatchFillValues contains the fill values to use for Vector matching +/// when one side does not find a match on the other side. +/// When a fill value is nil, no fill is applied for that side, and there +/// is no output for the match group if there is no match. +#[derive(Debug, Clone, PartialEq, Default)] +#[cfg_attr(feature = "ser", derive(serde::Serialize))] +pub struct VectorMatchFillValues { + pub rhs: Option, + pub lhs: Option, +} + +impl VectorMatchFillValues { + pub fn new(lhs: f64, rhs: f64) -> Self { + Self { + rhs: Some(rhs), + lhs: Some(lhs), + } + } + + pub fn with_rhs(mut self, rhs: f64) -> Self { + self.rhs = Some(rhs); + self + } + + pub fn with_lhs(mut self, lhs: f64) -> Self { + self.lhs = Some(lhs); + self + } +} + /// Binary Expr Modifier -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq)] pub struct BinModifier { /// The matching behavior for the operation if both operands are Vectors. /// If they are not this field is None. @@ -112,6 +142,9 @@ pub struct BinModifier { pub matching: Option, /// If a comparison operator, return 0/1 rather than filtering. pub return_bool: bool, + /// Fill-in values to use when a series from one side does not find a match + /// on the other side. + pub fill_values: VectorMatchFillValues, } impl fmt::Display for BinModifier { @@ -132,6 +165,21 @@ impl fmt::Display for BinModifier { _ => (), } + if self.fill_values.rhs.is_some() || self.fill_values.lhs.is_some() { + if self.fill_values.rhs == self.fill_values.lhs { + let fill_value = self.fill_values.rhs.unwrap(); + write!(s, "fill ({fill_value}) ")?; + } else { + if let Some(fill_value) = self.fill_values.lhs { + write!(s, "fill_left ({fill_value}) ")?; + } + + if let Some(fill_value) = self.fill_values.rhs { + write!(s, "fill_right ({fill_value}) ")?; + } + } + } + if s.trim().is_empty() { write!(f, "") } else { @@ -146,6 +194,7 @@ impl Default for BinModifier { card: VectorMatchCardinality::OneToOne, matching: None, return_bool: false, + fill_values: VectorMatchFillValues::default(), } } } @@ -166,6 +215,11 @@ impl BinModifier { self } + pub fn with_fill_values(mut self, fill_values: VectorMatchFillValues) -> Self { + self.fill_values = fill_values; + self + } + pub fn is_labels_joint(&self) -> bool { matches!( (self.card.labels(), &self.matching), @@ -255,6 +309,7 @@ where "include": [], "labels": labels, "on": true, + "fillValues": t.fill_values, }); map.serialize_value(&value)?; } @@ -264,6 +319,7 @@ where "include": [], "labels": labels, "on": false, + "fillValues": t.fill_values, }); map.serialize_value(&value)?; } @@ -274,6 +330,7 @@ where "include": [], "labels": [], "on": false, + "fillValues": t.fill_values, }); map.serialize_entry("matching", &value)?; } @@ -322,7 +379,7 @@ where map.end() } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq)] pub enum Offset { Pos(Duration), Neg(Duration), @@ -359,7 +416,7 @@ impl fmt::Display for Offset { } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq)] pub enum AtModifier { Start, End, @@ -487,7 +544,7 @@ impl fmt::Display for EvalStmt { /// ``` /// /// parameter is only required for `count_values`, `quantile`, `topk` and `bottomk`. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "ser", derive(serde::Serialize))] pub struct AggregateExpr { /// The used aggregation operation. @@ -544,7 +601,7 @@ impl Prettier for AggregateExpr { } /// UnaryExpr will negate the expr -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq)] pub struct UnaryExpr { pub expr: Box, } @@ -587,7 +644,7 @@ impl serde::Serialize for UnaryExpr { /// on(