diff --git a/src/query/mod.rs b/src/query/mod.rs index 8f463aa10c4423a3603f54f7bb3745973432a241..75bc237b7c23aca1d7b9a6d6d0b6304d85f6feb2 100644 --- a/src/query/mod.rs +++ b/src/query/mod.rs @@ -3,11 +3,12 @@ //! [`Metric`] and [`Scalar`] are the basic types used for building queries. //! For building complex queries involving operators, see module [`ops`]. -use std::fmt::Display; - +use self::ops::Operable; use crate::seal::Sealed; +use std::fmt::Display; -use self::ops::Operable; +#[cfg(feature = "metricsql")] +use ops::modifiers::KeepNames; pub mod fns; pub mod ops; @@ -450,6 +451,14 @@ pub trait QueryExt: Operable { { SubQry::new(self, dur) } + + #[cfg(feature = "metricsql")] + fn keep_metric_names(self) -> KeepNames<Self> + where + Self: Sized, + { + KeepNames(self) + } } impl<T: Operable> QueryExt for T {} diff --git a/src/query/ops/modifiers.rs b/src/query/ops/modifiers.rs index 6cd40966957d70c4ad5228411d9f3cb52a8bb5f9..e9b2ae7f5585a40d2cf60db7759cdd19cab98db1 100644 --- a/src/query/ops/modifiers.rs +++ b/src/query/ops/modifiers.rs @@ -1,5 +1,9 @@ use std::fmt::Display; +use crate::{query::IntoQuery, seal::Sealed}; + +use super::Operable; + #[derive(Debug, Clone, Default)] pub(crate) struct Mod<'a, M> { mod_type: M, @@ -114,3 +118,42 @@ impl Display for Mod<'_, AggrType> { Ok(()) } } + +/// MetricsQL's `keep_metric_names` modifier +/// +/// This modifier can only be applied using the `keep_metric_names` method made available by the [`QueryExt`](crate::query::QueryExt) trait. +#[cfg(feature = "metricsql")] +#[derive(Debug, Clone)] +pub struct KeepNames<E: Operable>(pub(crate) E); + +#[cfg(feature = "metricsql")] +impl<E: Operable> Display for KeepNames<E> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{exp} keep_metric_names", exp = self.0) + } +} + +#[cfg(feature = "metricsql")] +impl<E: Operable> Sealed for KeepNames<E> {} +#[cfg(feature = "metricsql")] +impl<E: Operable> Operable for KeepNames<E> {} + +#[cfg(feature = "metricsql")] +impl<E: Operable> IntoQuery for KeepNames<E> { + type Target = String; + fn into_query(self) -> Self::Target { + self.to_string() + } +} + +#[cfg(test)] +mod tests { + use crate::query::{Metric, QueryExt}; + + #[cfg(feature = "metricsql")] + #[test] + fn keep_names() { + let qry = Metric::new("metric").keep_metric_names(); + assert_eq!(qry.to_string(), "metric keep_metric_names"); + } +} diff --git a/tests/operators.rs b/tests/operators.rs index a27ce155e8ed9b0822264b2a84d99a1a18b3d825..9813aaa2df25331951285a0a2a7042b0934e890d 100644 --- a/tests/operators.rs +++ b/tests/operators.rs @@ -1,6 +1,6 @@ use mquery::query::{ ops::{Arithmetic, Comparison, Logical}, - Metric, Scalar, + Metric, QueryExt, Scalar, }; mod utils; @@ -89,3 +89,12 @@ async fn logical_set() { .unless(Metric::new("fourth_metric")); utils::send_query(query).await.unwrap(); } + +#[cfg(feature = "metricsql")] +#[tokio::test] +async fn keep_metric_names_mod() { + let query = Metric::new("metric") + .add(Metric::new("metric2")) + .keep_metric_names(); + utils::send_query(query).await.unwrap(); +}