rust_ef/query/builder/
filter.rs1use std::marker::PhantomData;
4
5use crate::entity::IEntityType;
6use crate::provider::DbValue;
7
8use super::super::ast::{
9 BoolExpr, FilterCondition, InSubquerySpec, OrderBy, OrderDirection, SubquerySpec,
10};
11use super::super::compile::{collect_bool_expr_values, filters_to_and_expr};
12use super::super::state::QueryState;
13use super::core::QueryBuilder;
14
15impl<T: IEntityType> QueryBuilder<T> {
16 #[doc(hidden)]
17 pub fn filter_column(
18 mut self,
19 column: &str,
20 operator: &str,
21 value: impl Into<DbValue>,
22 ) -> Self {
23 let db_val = value.into();
24 self.state.parameters.push(db_val);
25 self.state
26 .append_filter(FilterCondition::new(column, operator, 1));
27 self
28 }
29
30 #[doc(hidden)]
31 pub fn filter_not(mut self, column: &str, operator: &str, value: impl Into<DbValue>) -> Self {
32 let db_val = value.into();
33 self.state.parameters.push(db_val);
34 self.state
35 .append_bool_expr(BoolExpr::Not(Box::new(BoolExpr::Filter(
36 FilterCondition::new(column, operator, 1),
37 ))));
38 self
39 }
40
41 #[doc(hidden)]
42 pub fn filter_in(mut self, column: &str, values: Vec<DbValue>) -> Self {
43 let count = values.len();
44 for v in values {
45 self.state.parameters.push(v);
46 }
47 self.state
48 .append_filter(FilterCondition::new(column, "IN", count));
49 self
50 }
51
52 #[doc(hidden)]
53 pub fn filter_not_in(mut self, column: &str, values: Vec<DbValue>) -> Self {
54 let count = values.len();
55 for v in values {
56 self.state.parameters.push(v);
57 }
58 self.state
59 .append_bool_expr(BoolExpr::Not(Box::new(BoolExpr::Filter(
60 FilterCondition::new(column, "IN", count),
61 ))));
62 self
63 }
64
65 #[doc(hidden)]
66 pub fn filter_is_null(mut self, column: &str) -> Self {
67 self.state
68 .append_filter(FilterCondition::new(column, "IS NULL", 0));
69 self
70 }
71
72 #[doc(hidden)]
73 pub fn filter_is_not_null(mut self, column: &str) -> Self {
74 self.state
75 .append_filter(FilterCondition::new(column, "IS NOT NULL", 0));
76 self
77 }
78
79 #[doc(hidden)]
80 pub fn filter_between(
81 mut self,
82 column: &str,
83 low: impl Into<DbValue>,
84 high: impl Into<DbValue>,
85 ) -> Self {
86 let lo: DbValue = low.into();
87 let hi: DbValue = high.into();
88 self.state.parameters.push(lo);
89 self.state.parameters.push(hi);
90 self.state
91 .append_filter(FilterCondition::new(column, "BETWEEN", 2));
92 self
93 }
94
95 #[doc(hidden)]
96 pub fn filter_like(self, column: &str, pattern: impl Into<DbValue>) -> Self {
97 self.filter_column(column, "LIKE", pattern)
98 }
99
100 #[doc(hidden)]
101 pub fn filter_not_like(self, column: &str, pattern: impl Into<DbValue>) -> Self {
102 self.filter_not(column, "LIKE", pattern)
103 }
104
105 #[doc(hidden)]
106 pub fn order_by_column(mut self, column: &str) -> Self {
107 self.state
108 .orderings
109 .push(OrderBy::new(column, OrderDirection::Ascending));
110 self
111 }
112
113 #[doc(hidden)]
114 pub fn order_by_desc_column(mut self, column: &str) -> Self {
115 self.state
116 .orderings
117 .push(OrderBy::new(column, OrderDirection::Descending));
118 self
119 }
120
121 pub fn distinct(mut self) -> Self {
123 self.state.distinct = true;
124 self
125 }
126
127 #[doc(hidden)]
128 pub fn or_where(mut self, f: impl FnOnce(QueryBuilder<T>) -> QueryBuilder<T>) -> Self {
129 let sub = f(QueryBuilder {
130 state: QueryState::new(&self.state.from),
131 provider: self.provider.clone(),
132 filter_map: None,
133 lazy_loading_enabled: false,
134 _phantom: PhantomData,
135 });
136 let right = sub.state.where_expr.or_else(|| {
137 if sub.state.filters.is_empty() {
138 None
139 } else {
140 Some(filters_to_and_expr(&sub.state.filters))
141 }
142 });
143 if let Some(right_expr) = right {
144 self.state.where_expr = Some(match self.state.where_expr.take() {
145 None => right_expr,
146 Some(left) => BoolExpr::Or(Box::new(left), Box::new(right_expr)),
147 });
148 self.state.parameters.extend(sub.state.parameters);
149 self.state.filters.extend(sub.state.filters);
150 }
151 self
152 }
153
154 pub fn where_exists_internal(
164 mut self,
165 nav_field: &'static str,
166 related_type: &'static str,
167 predicate: Option<BoolExpr>,
168 negated: bool,
169 ) -> Self {
170 let mut spec = SubquerySpec::new(nav_field, related_type);
171 if let Some(pred) = predicate {
172 let values = collect_bool_expr_values(&pred);
173 self.state.parameters.extend(values);
174 spec.predicate = Some(Box::new(pred));
175 }
176 let expr = if negated {
177 BoolExpr::NotExists(Box::new(spec))
178 } else {
179 BoolExpr::Exists(Box::new(spec))
180 };
181 self.state.append_bool_expr(expr);
182 self
183 }
184
185 pub fn where_in_subquery_internal(
197 mut self,
198 outer_column: &'static str,
199 source_table: &'static str,
200 projection_column: &'static str,
201 predicate: Option<BoolExpr>,
202 negated: bool,
203 ) -> Self {
204 let mut spec = InSubquerySpec::new(outer_column, source_table, projection_column);
205 if let Some(pred) = predicate {
206 let values = collect_bool_expr_values(&pred);
207 self.state.parameters.extend(values);
208 spec.predicate = Some(Box::new(pred));
209 }
210 let expr = if negated {
211 BoolExpr::NotInSubquery(Box::new(spec))
212 } else {
213 BoolExpr::InSubquery(Box::new(spec))
214 };
215 self.state.append_bool_expr(expr);
216 self
217 }
218
219 pub fn skip(mut self, count: usize) -> Self {
221 self.state.offset = Some(count);
222 self
223 }
224
225 pub fn take(mut self, count: usize) -> Self {
227 self.state.limit = Some(count);
228 self
229 }
230}