Skip to content
Snippets Groups Projects
Commit 79650cb5 authored by Maaz Ahmed's avatar Maaz Ahmed
Browse files

Merge branch '32-qol-pipe-map-functionality-built-into-library' into 'main'

QueryExt Trait

Closes #32

See merge request !20
parents 711c2863 e9ee6859
No related tags found
1 merge request!20QueryExt Trait
Pipeline #14710 passed with stages
in 1 minute and 20 seconds
......@@ -273,7 +273,7 @@ impl ops::Operable for Scalar {}
///
/// This also allows combining complex queries, especially when a function is generic over a single type
/// `T` that implements `Operable`, you can convert the existing type into this to make it work.
/// This can be done easily with the [`Expression`] trait which has a blanket implementation for all types
/// This can be done easily with the [`QueryExt`] trait which has a blanket implementation for all types
/// which implement [`Operable`] (all query builder API types).
///
/// Note: This is generally not recommended unless it is necessary to use. This is because the query builder
......@@ -320,30 +320,6 @@ impl From<String> for RawExpr {
}
}
/// Helper trait to convert a query builder API type into a [`RawExpr`] type
///
/// This is useful when a function takes a sequence (array/vector/iterator) of a generic type `T: Operable`
/// but you want to combine different types (produced from query fns or other complex types).
///
/// This trait has a blanket implementation for all `T` that implement `Display` which include types
/// that implement `Operable`
///
/// While the `String` type could have been allowed to be part of the builder API directly,
/// it is by design that a user must explicitly turn a string into a [`RawExpr`] saying that
/// they're opting in to use a raw string in the query builder API.
pub trait Expression {
/// Build the query early and produce a [`RawExpr`]
///
/// See the type's documentation for additional details.
fn to_expr(&self) -> RawExpr;
}
impl<T: Display> Expression for T {
fn to_expr(&self) -> RawExpr {
RawExpr(self.to_string())
}
}
impl IntoQuery for RawExpr {
type Target = String;
fn into_query(self) -> Self::Target {
......@@ -360,6 +336,54 @@ impl Display for RawExpr {
}
}
/// Additional/extended query builder API functionality
///
/// This trait has a blanket implementation for all types that implement [`Operable`]
pub trait QueryExt {
/// Convert a query builder API type into a [`RawExpr`] type
///
/// This is useful when a function takes a sequence (array/vector/iterator) of a generic type `T: Operable`
/// but you want to combine different types (produced from query fns or other complex types).
///
/// While the `String` type could have been allowed to be part of the builder API directly,
/// it is by design that a user must explicitly turn a string into a [`RawExpr`] saying that
/// they're opting in to use a raw string in the query builder API.
fn to_expr(&self) -> RawExpr;
/// Call a function or closure on `Self` to transform it into another type
///
/// This is similar to the `Iterator's` `map` method, except this is eagerly evaluated and operates on a single item.
/// This is useful for building complex queries that have many nested functions.
///
/// For example:
/// ```
/// # use mquery::query::{Metric, QueryExt, fns::aggregate::sum};
/// // the usual way
/// let nest = sum(Metric::new("http_requests"));
/// // with `then`
/// let chain = Metric::new("http_requests").then(sum);
/// assert_eq!(nest.to_string(), chain.to_string());
/// ```
///
/// > Note: the reason this function is called `then` instead of `pipe` or `map` is because `then` semantically provides a clearer
/// > idea of what's happening when writing/reading the complex queries.
fn then<R>(self, func: impl FnOnce(Self) -> R) -> R
where
Self: Sized;
}
impl<T: Operable> QueryExt for T {
fn to_expr(&self) -> RawExpr {
RawExpr(self.to_string())
}
fn then<R>(self, func: impl FnOnce(Self) -> R) -> R
where
Self: Sized,
{
func(self)
}
}
#[cfg(test)]
mod tests {
use super::*;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment