pub struct Predicate<T: IEntityType> { /* private fields */ }Expand description
A composable WHERE predicate for entity type T.
T tags the predicate so that fragments written for different entities do
not silently combine or get applied to the wrong query builder.
use rust_ef::prelude::*;
use rust_ef::query::QueryBuilder;
#[derive(Debug, Clone, EntityType)]
#[table("products")]
struct Product {
#[primary_key]
id: i32,
name: String,
description: String,
price: f64,
is_deleted: bool,
}
fn product_filter(keyword: Option<&str>, min_price: Option<f64>) -> Predicate<Product> {
let keyword_group = keyword.map(|keyword| {
linq!(|p: Product| p.name.contains(keyword))
.or(linq!(|p: Product| p.description.contains(keyword)))
});
let min_price = min_price.map(|min_price| linq!(|p: Product| p.price >= min_price));
// always() 是 AND 链起点,本身不产生 SQL;
// and_opt 让「可选条件」不需要额外 if let。
Predicate::<Product>::always()
.and(linq!(|p: Product| !p.is_deleted))
.and_opt(keyword_group)
.and_opt(min_price)
}
let predicate = product_filter(Some("rust"), Some(9.9));
let sql = QueryBuilder::<Product>::new("products")
.filter(predicate)
.to_sql();
// NOT (is_deleted = ?) AND ((name LIKE ?) OR (description LIKE ?)) AND (price >= ?)
assert!(sql.contains("(name LIKE ?) OR (description LIKE ?)"));Implementations§
Source§impl<T: IEntityType> Predicate<T>
impl<T: IEntityType> Predicate<T>
Sourcepub fn always() -> Self
pub fn always() -> Self
A predicate that matches every row — the seed of an AND chain.
Predicate::always().and(p) is p, so seeding with it adds no SQL.
Sourcepub fn never() -> Self
pub fn never() -> Self
A predicate that matches no row — the seed of an OR chain.
Predicate::never().or(p) is p, so seeding with it adds no SQL.
Sourcepub fn from_expr(expr: BoolExpr) -> Self
pub fn from_expr(expr: BoolExpr) -> Self
Wraps an expression tree as a predicate.
Prefer linq!(|b: T| ...), which is already typed and
self-contained. This is the unchecked door for reusing a BoolExpr
produced elsewhere (e.g. a filter read back from ModelBuilder).
Sourcepub fn and(self, other: impl Into<Predicate<T>>) -> Self
pub fn and(self, other: impl Into<Predicate<T>>) -> Self
self AND other.
always() is the identity (always().and(p) == p) and never() is
absorbing (never().and(p) == never()), so identities never leak into
the generated SQL.
Sourcepub fn and_opt(self, other: Option<impl Into<Predicate<T>>>) -> Self
pub fn and_opt(self, other: Option<impl Into<Predicate<T>>>) -> Self
self AND other when other is Some — the one-liner for an optional
filter. None leaves the predicate unchanged.
Sourcepub fn or(self, other: impl Into<Predicate<T>>) -> Self
pub fn or(self, other: impl Into<Predicate<T>>) -> Self
self OR other.
never() is the identity (never().or(p) == p) and always() is
absorbing (always().or(p) == always()).