From a6612c24db670169d7f00cea6bb976bc37bd485a Mon Sep 17 00:00:00 2001 From: Maaz Ahmed <maaz.a@subcom.tech> Date: Wed, 27 Dec 2023 08:42:02 +0000 Subject: [PATCH] feat: add support for more functions (transform) --- src/query/fns/mod.rs | 1 - src/query/fns/transform.rs | 124 ++++++++++++++++++++++++++++++++++++- tests/fns.rs | 24 +++++++ 3 files changed, 147 insertions(+), 2 deletions(-) diff --git a/src/query/fns/mod.rs b/src/query/fns/mod.rs index 6314ea1..0b10770 100644 --- a/src/query/fns/mod.rs +++ b/src/query/fns/mod.rs @@ -19,7 +19,6 @@ pub mod aggregate; #[cfg(feature = "metricsql")] pub mod label; pub mod rollup; -#[cfg(feature = "metricsql")] pub mod transform; // This macro takes a name and formatting arguments which are directly passed to the `write` macro diff --git a/src/query/fns/transform.rs b/src/query/fns/transform.rs index 7a8b1e8..9e2f3a8 100644 --- a/src/query/fns/transform.rs +++ b/src/query/fns/transform.rs @@ -5,6 +5,7 @@ use crate::query::ops::Operable; use super::{qry_fn, QryFunc}; /// MetricsQL `limit_offset` query function +#[cfg(feature = "metricsql")] pub fn mql_limit_offset( limit: usize, offset: usize, @@ -14,6 +15,7 @@ pub fn mql_limit_offset( } /// MetricsQL `union` query function +#[cfg(feature = "metricsql")] pub fn mql_union( qry_expressions: &[impl Operable], ) -> QryFunc<impl Fn(&mut fmt::Formatter) -> fmt::Result + '_> { @@ -28,11 +30,131 @@ pub fn mql_union( ) } +/// The `round` query transform function +pub fn round( + vec_expr: impl Operable + 'static, + nearest: Option<f64>, +) -> QryFunc<impl Fn(&mut fmt::Formatter) -> fmt::Result> { + qry_fn!(round, { + |f| { + if let Some(near) = nearest { + return write!(f, "{vec_expr}, {near}"); + } + write!(f, "{vec_expr}") + } + }) +} + +/// The `abs` query transform function +pub fn abs( + vec_expr: impl Operable + 'static, +) -> QryFunc<impl Fn(&mut fmt::Formatter) -> fmt::Result> { + qry_fn!(abs, "{vec_expr}") +} + +/// The `absent` query transform function +pub fn absent( + vec_expr: impl Operable + 'static, +) -> QryFunc<impl Fn(&mut fmt::Formatter) -> fmt::Result> { + qry_fn!(absent, "{vec_expr}") +} + +/// The `ceil` query transform function +pub fn ceil( + vec_expr: impl Operable + 'static, +) -> QryFunc<impl Fn(&mut fmt::Formatter) -> fmt::Result> { + qry_fn!(ceil, "{vec_expr}") +} + +/// The `changes` query transform function +pub fn changes( + vec_expr: impl Operable + 'static, +) -> QryFunc<impl Fn(&mut fmt::Formatter) -> fmt::Result> { + qry_fn!(changes, "{vec_expr}") +} + +/// The `delta` query transform function +pub fn delta( + vec_expr: impl Operable + 'static, +) -> QryFunc<impl Fn(&mut fmt::Formatter) -> fmt::Result> { + qry_fn!(delta, "{vec_expr}") +} +/// The `exp` query transform function +pub fn exp( + vec_expr: impl Operable + 'static, +) -> QryFunc<impl Fn(&mut fmt::Formatter) -> fmt::Result> { + qry_fn!(exp, "{vec_expr}") +} +/// The `floor` query transform function +pub fn floor( + vec_expr: impl Operable + 'static, +) -> QryFunc<impl Fn(&mut fmt::Formatter) -> fmt::Result> { + qry_fn!(floor, "{vec_expr}") +} + +/// The `sort` query transform function +pub fn sort( + vec_expr: impl Operable + 'static, +) -> QryFunc<impl Fn(&mut fmt::Formatter) -> fmt::Result> { + qry_fn!(sort, "{vec_expr}") +} + +/// The `sort_desc` query transform function +pub fn sort_desc( + vec_expr: impl Operable + 'static, +) -> QryFunc<impl Fn(&mut fmt::Formatter) -> fmt::Result> { + qry_fn!(sort_desc, "{vec_expr}") +} + +/// The `sqrt` query transform function +pub fn sqrt( + vec_expr: impl Operable + 'static, +) -> QryFunc<impl Fn(&mut fmt::Formatter) -> fmt::Result> { + qry_fn!(sqrt, "{vec_expr}") +} + +/// The `vector` query transform function +pub fn vector(scalar: f64) -> QryFunc<impl Fn(&mut fmt::Formatter) -> fmt::Result> { + qry_fn!(vector, "{scalar}") +} + #[cfg(test)] mod tests { - use super::*; use crate::query::Metric; + macro_rules! test_transform { + ($($name:tt),+) => { + $( + #[test] + fn $name() { + let qry = super::$name(Metric::new("metric")).to_string(); + assert_eq!(qry, concat!(stringify!($name), "(metric)")) + } + )+ + }; + } + + #[test] + fn round() { + let qry = super::round(Metric::new("metric"), Some(2.0)).to_string(); + assert_eq!(qry, "round(metric, 2)"); + } + + #[test] + fn vector() { + let qry = super::vector(1.5).to_string(); + assert_eq!(qry, "vector(1.5)"); + } + + test_transform!(abs, absent, ceil, changes, delta, exp, floor, sort, sort_desc, sqrt); +} + +#[cfg(all(test, feature = "metricsql"))] +mod mql_tests { + use crate::query::Metric; + + use super::*; + #[test] fn trans_limit_offset() { let query = mql_limit_offset(1, 2, Metric::new("metric")).to_string(); diff --git a/tests/fns.rs b/tests/fns.rs index 15c2521..da305a8 100644 --- a/tests/fns.rs +++ b/tests/fns.rs @@ -34,6 +34,16 @@ macro_rules! label_tests { }; } +macro_rules! transform_tests { + ($($fn_name: tt),+) => { + $(#[tokio::test] + async fn $fn_name() { + let query = transform::$fn_name(Metric::new("metric")); + utils::send_query(query).await.unwrap(); + })+ + }; +} + aggr_tests!(sum, min, max, avg, group, stddev, stdvar, count); #[tokio::test] @@ -98,6 +108,8 @@ label_tests!( mql_sort_by_label_numeric_desc ); +transform_tests!(abs, absent, ceil, changes, delta, exp, floor, sort, sort_desc, sqrt); + #[tokio::test] async fn trans_limit_offset() { let query = transform::mql_limit_offset(1, 2, Metric::new("metric")).to_string(); @@ -109,3 +121,15 @@ async fn trans_union() { let query = transform::mql_union(&[Metric::new("metric"), Metric::new("metric2")]).to_string(); utils::send_query(query).await.unwrap(); } + +#[tokio::test] +async fn trans_round() { + let query = transform::round(Metric::new("metric"), Some(1.0)); + utils::send_query(query).await.unwrap(); +} + +#[tokio::test] +async fn trans_vector() { + let query = transform::vector(1.0); + utils::send_query(query).await.unwrap(); +} -- GitLab