Skip to content

Commit

Permalink
add last_filter_action to mark the last append type
Browse files Browse the repository at this point in the history
  • Loading branch information
groobyming committed May 16, 2024
1 parent 1110f9b commit 7ffea98
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 26 deletions.
61 changes: 41 additions & 20 deletions src/label/matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,21 @@ fn try_escape_for_repeat_re(re: &str) -> String {
pub struct Matchers {
pub matchers: Vec<Matcher>,
pub or_matchers: Vec<Vec<Matcher>>,
pub last_filter_action: FilterActionType,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FilterActionType {
AND,
OR,
}

impl Matchers {
pub fn empty() -> Self {
Self {
matchers: vec![],
or_matchers: vec![],
last_filter_action: FilterActionType::AND,
}
}

Expand All @@ -201,47 +209,54 @@ impl Matchers {
Self {
matchers,
or_matchers: vec![],
last_filter_action: FilterActionType::AND,
}
}

pub fn new(matchers: Vec<Matcher>) -> Self {
Self {
matchers,
or_matchers: vec![],
last_filter_action: FilterActionType::AND,
}
}

pub fn new_or(or_matchers: Vec<Vec<Matcher>>) -> Self {
Self {
matchers: vec![],
or_matchers,
}
}

pub fn new_mixed(matchers: Vec<Matcher>, or_matchers: Vec<Vec<Matcher>>) -> Self {
Self {
matchers,
or_matchers,
}
pub fn with_or_matchers(mut self, or_matchers: Vec<Vec<Matcher>>) -> Self {
self.or_matchers = or_matchers;
self
}

pub fn append(mut self, matcher: Matcher) -> Self {
self.matchers.push(matcher);
self.last_filter_action = FilterActionType::AND;
self
}

pub fn append_or(mut self, matcher: Matcher) -> Self {
let latest_or_matchers = self.or_matchers.pop();
if let Some(mut latest_or_matchers) = latest_or_matchers {
latest_or_matchers.push(matcher);
self.or_matchers.push(latest_or_matchers);
match self.last_filter_action {
FilterActionType::AND => {
self.or_matchers.push(latest_or_matchers);
let latest_matcher = self.matchers.pop();
if let Some(latest_matcher) = latest_matcher {
let or_matcher_pair = vec![latest_matcher, matcher];
self.or_matchers.push(or_matcher_pair);
}
}
FilterActionType::OR => {
latest_or_matchers.push(matcher);
self.or_matchers.push(latest_or_matchers);
}
}
} else {
let latest_matcher = self.matchers.pop();
if let Some(latest_matcher) = latest_matcher {
let or_matcher_pair = vec![latest_matcher, matcher];
self.or_matchers.push(or_matcher_pair);
}
}
self.last_filter_action = FilterActionType::OR;
self
}

Expand Down Expand Up @@ -287,20 +302,26 @@ impl fmt::Display for Matchers {
if or_matchers.is_empty() {
write!(f, "{}", join_vector(simple_matchers, ",", true))
} else {
let or_matchers_str = self.or_matchers.iter().fold(String::new(), |_, pair| {
format!("{},", join_vector(pair, " or ", true))
});
let or_matchers_str =
self.or_matchers
.iter()
.fold(String::new(), |or_matchers_str, pair| {
format!("{}, {}", or_matchers_str, join_vector(pair, " or ", true))
});
let or_matchers_str = or_matchers_str
.trim_start_matches(',')
.trim_end_matches(',');
.trim_end_matches(',')
.trim();
let simple_matchers_str = join_vector(simple_matchers, ",", true).to_string();
let simple_matchers_str = simple_matchers_str
.trim_start_matches(',')
.trim_end_matches(',');
.trim_end_matches(',')
.trim();
let last_matchers_str = format!("{},{}", simple_matchers_str, or_matchers_str);
let last_matchers_str = last_matchers_str
.trim_start_matches(',')
.trim_end_matches(',');
.trim_end_matches(',')
.trim();
write!(f, "{}", last_matchers_str)
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/label/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use std::collections::HashSet;
use std::fmt;

mod matcher;
pub use matcher::{MatchOp, Matcher, Matchers};
pub use matcher::{FilterActionType, MatchOp, Matcher, Matchers};

/// "__name__"
pub const METRIC_NAME: &str = "__name__";
Expand Down
19 changes: 14 additions & 5 deletions src/parser/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub fn parse(input: &str) -> Result<Expr, String> {
mod tests {
use regex::Regex;

use crate::label::{Labels, MatchOp, Matcher, Matchers, METRIC_NAME};
use crate::label::{FilterActionType, Labels, MatchOp, Matcher, Matchers, METRIC_NAME};
use crate::parser;
use crate::parser::function::get_function;
use crate::parser::{
Expand Down Expand Up @@ -2125,36 +2125,40 @@ mod tests {
Expr::new_vector_selector(Some(String::from("foo")), matchers)
}),
(r#"foo{label1="1" or label2="2"}"#, {
let matchers = Matchers::new_or(vec![vec![
let mut matchers = Matchers::new(vec![]).with_or_matchers(vec![vec![
Matcher::new(MatchOp::Equal, "label1", "1"),
Matcher::new(MatchOp::Equal, "label2", "2"),
]]);
matchers.last_filter_action = FilterActionType::OR;
Expr::new_vector_selector(Some(String::from("foo")), matchers)
}),
(r#"foo{label1="1" or or="or"}"#, {
let matchers = Matchers::new_or(vec![vec![
let mut matchers = Matchers::new(vec![]).with_or_matchers(vec![vec![
Matcher::new(MatchOp::Equal, "label1", "1"),
Matcher::new(MatchOp::Equal, "or", "or"),
]]);
matchers.last_filter_action = FilterActionType::OR;
Expr::new_vector_selector(Some(String::from("foo")), matchers)
}),
(r#"foo{label1="1" or label2="2" or label3="3"}"#, {
let matchers = Matchers::new_or(vec![vec![
let mut matchers = Matchers::new(vec![]).with_or_matchers(vec![vec![
Matcher::new(MatchOp::Equal, "label1", "1"),
Matcher::new(MatchOp::Equal, "label2", "2"),
Matcher::new(MatchOp::Equal, "label3", "3"),
]]);
matchers.last_filter_action = FilterActionType::OR;
Expr::new_vector_selector(Some(String::from("foo")), matchers)
}),
(
r#"foo{label1="1" or label2="2" or label3="3" or label4="4"}"#,
{
let matchers = Matchers::new_or(vec![vec![
let mut matchers = Matchers::new(vec![]).with_or_matchers(vec![vec![
Matcher::new(MatchOp::Equal, "label1", "1"),
Matcher::new(MatchOp::Equal, "label2", "2"),
Matcher::new(MatchOp::Equal, "label3", "3"),
Matcher::new(MatchOp::Equal, "label4", "4"),
]]);
matchers.last_filter_action = FilterActionType::OR;
Expr::new_vector_selector(Some(String::from("foo")), matchers)
},
),
Expand Down Expand Up @@ -2186,6 +2190,11 @@ mod tests {
let expr = parser::parse(promql).unwrap();
assert_eq!(expr.to_string(), expected);

let promql = r#"a{label1="1" or label2="2" or label3="3", label4="4" or label5="5"}"#;
let expected = r#"a{label1="1" or label2="2" or label3="3", label4="4" or label5="5"}"#;
let expr = parser::parse(promql).unwrap();
assert_eq!(expr.to_string(), expected);

let fail_cases = vec![
(
r#"foo{or}"#,
Expand Down

0 comments on commit 7ffea98

Please sign in to comment.