Skip to main content

rust_ef/query/builder/
filter.rs

1//! Predicates, ordering, distinct, and pagination methods.
2
3use crate::entity::IEntityType;
4
5use super::super::ast::{OrderBy, OrderDirection};
6use super::super::predicate::Predicate;
7use super::core::QueryBuilder;
8
9impl<T: IEntityType> QueryBuilder<T> {
10    #[doc(hidden)]
11    pub fn order_by_column(mut self, column: &str) -> Self {
12        self.state
13            .orderings
14            .push(OrderBy::new(column, OrderDirection::Ascending));
15        self
16    }
17
18    #[doc(hidden)]
19    pub fn order_by_desc_column(mut self, column: &str) -> Self {
20        self.state
21            .orderings
22            .push(OrderBy::new(column, OrderDirection::Descending));
23        self
24    }
25
26    /// Marks this query as `SELECT DISTINCT`.
27    pub fn distinct(mut self) -> Self {
28        self.state.distinct = true;
29        self
30    }
31
32    /// Appends a predicate with `AND`.
33    ///
34    /// Accepts a [`Predicate`] — `linq!(|b: T| ...)` combined with
35    /// [`Predicate::and`] / [`Predicate::or`] / [`Predicate::not`] — or a bare
36    /// [`BoolExpr`](super::super::ast::BoolExpr). The predicate's bound values
37    /// are registered in tree order, so they line up with the generated
38    /// placeholders.
39    ///
40    /// Conditions accumulate with `AND`, and `Predicate::always()` adds no SQL,
41    /// which makes it safe to seed a chain and apply it unconditionally:
42    ///
43    /// ```ignore
44    /// let mut predicate = Predicate::<Product>::always();
45    /// predicate = predicate.and_opt(
46    ///     keyword.map(|keyword| linq!(|p: Product| p.name.contains(keyword))),
47    /// );
48    /// predicate = predicate.and_opt(
49    ///     min_price.map(|min_price| linq!(|p: Product| p.price >= min_price)),
50    /// );
51    /// let query = ctx.set::<Product>().query().filter(predicate);
52    /// ```
53    pub fn filter(self, predicate: impl Into<Predicate<T>>) -> Self {
54        match predicate.into().into_where_expr() {
55            Some(expr) => self.apply_query_filter(expr),
56            None => self,
57        }
58    }
59
60    /// Skips the specified number of rows.
61    pub fn skip(mut self, count: usize) -> Self {
62        self.state.offset = Some(count);
63        self
64    }
65
66    /// Takes the specified number of rows.
67    pub fn take(mut self, count: usize) -> Self {
68        self.state.limit = Some(count);
69        self
70    }
71}