1use crate::{EntityDescriptor, SelectQuery, Value};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum BinaryOp {
5 Eq,
6 Ne,
7 Gt,
8 Gte,
9 Lt,
10 Lte,
11 Like,
12 NotLike,
13 In,
14 NotIn,
15 InLarge,
16 NotInLarge,
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum ExprFunction {
21 Soundex,
22 Gbk,
23 Count,
24 Sum,
25 Avg,
26 Min,
27 Max,
28 Stddev,
29 StddevPop,
30 VarSamp,
31 VarPop,
32 BitAnd,
33 BitOr,
34 BitXor,
35}
36
37#[derive(Debug, Clone, PartialEq)]
38pub enum Expr {
39 Column(String),
40 Value(Value),
41 Function {
42 function: ExprFunction,
43 args: Vec<Expr>,
44 },
45 Binary {
46 left: Box<Expr>,
47 op: BinaryOp,
48 right: Box<Expr>,
49 },
50 SubQuery {
51 left: Box<Expr>,
52 op: BinaryOp,
53 entity: EntityDescriptor,
54 query: Box<SelectQuery>,
55 },
56 Between {
57 expr: Box<Expr>,
58 lower: Box<Expr>,
59 upper: Box<Expr>,
60 },
61 IsNull(Box<Expr>),
62 IsNotNull(Box<Expr>),
63 And(Vec<Expr>),
64 Or(Vec<Expr>),
65 Not(Box<Expr>),
66}
67
68impl Expr {
69 pub const LARGE_IN_THRESHOLD: usize = 20;
72
73 pub fn column(name: impl Into<String>) -> Self {
74 Self::Column(name.into())
75 }
76
77 pub fn value(value: impl Into<Value>) -> Self {
78 Self::Value(value.into())
79 }
80
81 pub fn function(function: ExprFunction, args: impl IntoIterator<Item = Expr>) -> Self {
82 Self::Function {
83 function,
84 args: args.into_iter().collect(),
85 }
86 }
87
88 pub fn soundex(expr: Expr) -> Self {
89 Self::function(ExprFunction::Soundex, [expr])
90 }
91
92 pub fn gbk(expr: Expr) -> Self {
93 Self::function(ExprFunction::Gbk, [expr])
94 }
95
96 pub fn count_all() -> Self {
97 Self::function(ExprFunction::Count, [])
98 }
99
100 pub fn count_expr(expr: Expr) -> Self {
101 Self::function(ExprFunction::Count, [expr])
102 }
103
104 pub fn sum_expr(expr: Expr) -> Self {
105 Self::function(ExprFunction::Sum, [expr])
106 }
107
108 pub fn avg_expr(expr: Expr) -> Self {
109 Self::function(ExprFunction::Avg, [expr])
110 }
111
112 pub fn min_expr(expr: Expr) -> Self {
113 Self::function(ExprFunction::Min, [expr])
114 }
115
116 pub fn max_expr(expr: Expr) -> Self {
117 Self::function(ExprFunction::Max, [expr])
118 }
119
120 pub fn stddev_expr(expr: Expr) -> Self {
121 Self::function(ExprFunction::Stddev, [expr])
122 }
123
124 pub fn stddev_pop_expr(expr: Expr) -> Self {
125 Self::function(ExprFunction::StddevPop, [expr])
126 }
127
128 pub fn var_samp_expr(expr: Expr) -> Self {
129 Self::function(ExprFunction::VarSamp, [expr])
130 }
131
132 pub fn var_pop_expr(expr: Expr) -> Self {
133 Self::function(ExprFunction::VarPop, [expr])
134 }
135
136 pub fn bit_and_expr(expr: Expr) -> Self {
137 Self::function(ExprFunction::BitAnd, [expr])
138 }
139
140 pub fn bit_or_expr(expr: Expr) -> Self {
141 Self::function(ExprFunction::BitOr, [expr])
142 }
143
144 pub fn bit_xor_expr(expr: Expr) -> Self {
145 Self::function(ExprFunction::BitXor, [expr])
146 }
147
148 pub fn sound_like(column: impl Into<String>, value: impl Into<Value>) -> Self {
149 Self::binary(
150 Self::soundex(Self::column(column)),
151 BinaryOp::Eq,
152 Self::soundex(Self::value(value)),
153 )
154 }
155
156 pub fn eq(column: impl Into<String>, value: impl Into<Value>) -> Self {
157 Self::binary(Self::column(column), BinaryOp::Eq, Self::value(value))
158 }
159
160 pub fn ne(column: impl Into<String>, value: impl Into<Value>) -> Self {
161 Self::binary(Self::column(column), BinaryOp::Ne, Self::value(value))
162 }
163
164 pub fn gt(column: impl Into<String>, value: impl Into<Value>) -> Self {
165 Self::binary(Self::column(column), BinaryOp::Gt, Self::value(value))
166 }
167
168 pub fn gte(column: impl Into<String>, value: impl Into<Value>) -> Self {
169 Self::binary(Self::column(column), BinaryOp::Gte, Self::value(value))
170 }
171
172 pub fn lt(column: impl Into<String>, value: impl Into<Value>) -> Self {
173 Self::binary(Self::column(column), BinaryOp::Lt, Self::value(value))
174 }
175
176 pub fn lte(column: impl Into<String>, value: impl Into<Value>) -> Self {
177 Self::binary(Self::column(column), BinaryOp::Lte, Self::value(value))
178 }
179
180 pub fn like(column: impl Into<String>, pattern: impl Into<String>) -> Self {
181 Self::binary(
182 Self::column(column),
183 BinaryOp::Like,
184 Self::value(pattern.into()),
185 )
186 }
187
188 pub fn not_like(column: impl Into<String>, pattern: impl Into<String>) -> Self {
189 Self::binary(
190 Self::column(column),
191 BinaryOp::NotLike,
192 Self::value(pattern.into()),
193 )
194 }
195
196 pub fn contain(column: impl Into<String>, value: impl Into<String>) -> Self {
197 Self::like(column, format!("%{}%", value.into()))
198 }
199
200 pub fn not_contain(column: impl Into<String>, value: impl Into<String>) -> Self {
201 Self::not_like(column, format!("%{}%", value.into()))
202 }
203
204 pub fn begin_with(column: impl Into<String>, value: impl Into<String>) -> Self {
205 Self::like(column, format!("{}%", value.into()))
206 }
207
208 pub fn not_begin_with(column: impl Into<String>, value: impl Into<String>) -> Self {
209 Self::not_like(column, format!("{}%", value.into()))
210 }
211
212 pub fn end_with(column: impl Into<String>, value: impl Into<String>) -> Self {
213 Self::like(column, format!("%{}", value.into()))
214 }
215
216 pub fn not_end_with(column: impl Into<String>, value: impl Into<String>) -> Self {
217 Self::not_like(column, format!("%{}", value.into()))
218 }
219
220 pub fn binary(left: Expr, op: BinaryOp, right: Expr) -> Self {
221 Self::Binary {
222 left: Box::new(left),
223 op,
224 right: Box::new(right),
225 }
226 }
227
228 pub fn compare_columns(
229 left_column: impl Into<String>,
230 op: BinaryOp,
231 right_column: impl Into<String>,
232 ) -> Self {
233 Self::binary(Self::column(left_column), op, Self::column(right_column))
234 }
235
236 pub fn in_list(column: impl Into<String>, values: impl IntoIterator<Item = Value>) -> Self {
237 let values = values.into_iter().collect::<Vec<_>>();
238 Self::binary(
239 Self::column(column),
240 if values.len() > Self::LARGE_IN_THRESHOLD {
241 BinaryOp::InLarge
242 } else {
243 BinaryOp::In
244 },
245 Self::Value(Value::List(values)),
246 )
247 }
248
249 pub fn not_in_list(column: impl Into<String>, values: impl IntoIterator<Item = Value>) -> Self {
250 let values = values.into_iter().collect::<Vec<_>>();
251 Self::binary(
252 Self::column(column),
253 if values.len() > Self::LARGE_IN_THRESHOLD {
254 BinaryOp::NotInLarge
255 } else {
256 BinaryOp::NotIn
257 },
258 Self::Value(Value::List(values)),
259 )
260 }
261
262 pub fn in_large(column: impl Into<String>, values: impl IntoIterator<Item = Value>) -> Self {
263 Self::binary(
264 Self::column(column),
265 BinaryOp::InLarge,
266 Self::Value(Value::List(values.into_iter().collect())),
267 )
268 }
269
270 pub fn not_in_large(
271 column: impl Into<String>,
272 values: impl IntoIterator<Item = Value>,
273 ) -> Self {
274 Self::binary(
275 Self::column(column),
276 BinaryOp::NotInLarge,
277 Self::Value(Value::List(values.into_iter().collect())),
278 )
279 }
280
281 pub fn in_subquery(
282 column: impl Into<String>,
283 entity: EntityDescriptor,
284 query: SelectQuery,
285 field: impl Into<String>,
286 ) -> Self {
287 Self::subquery(Self::column(column), BinaryOp::In, entity, query, field)
288 }
289
290 pub fn not_in_subquery(
291 column: impl Into<String>,
292 entity: EntityDescriptor,
293 query: SelectQuery,
294 field: impl Into<String>,
295 ) -> Self {
296 Self::subquery(Self::column(column), BinaryOp::NotIn, entity, query, field)
297 }
298
299 pub fn subquery(
300 left: Expr,
301 op: BinaryOp,
302 entity: EntityDescriptor,
303 mut query: SelectQuery,
304 field: impl Into<String>,
305 ) -> Self {
306 let field = field.into();
307 if matches!(op, BinaryOp::NotIn | BinaryOp::NotInLarge) {
311 query = query.and_filter(Self::is_not_null(field.clone()));
312 }
313 query.projection = vec![field];
314 Self::SubQuery {
315 left: Box::new(left),
316 op,
317 entity,
318 query: Box::new(query),
319 }
320 }
321
322 pub fn between(
323 column: impl Into<String>,
324 lower: impl Into<Value>,
325 upper: impl Into<Value>,
326 ) -> Self {
327 Self::Between {
328 expr: Box::new(Self::column(column)),
329 lower: Box::new(Self::value(lower)),
330 upper: Box::new(Self::value(upper)),
331 }
332 }
333
334 pub fn is_null(column: impl Into<String>) -> Self {
335 Self::IsNull(Box::new(Self::column(column)))
336 }
337
338 pub fn is_not_null(column: impl Into<String>) -> Self {
339 Self::IsNotNull(Box::new(Self::column(column)))
340 }
341
342 pub fn and(parts: impl IntoIterator<Item = Expr>) -> Self {
343 let mut unique = Vec::new();
344 for part in parts {
345 if !unique.contains(&part) {
346 unique.push(part);
347 }
348 }
349 Self::And(unique)
350 }
351
352 pub fn or(parts: impl IntoIterator<Item = Expr>) -> Self {
353 let mut unique = Vec::new();
354 for part in parts {
355 if !unique.contains(&part) {
356 unique.push(part);
357 }
358 }
359 Self::Or(unique)
360 }
361
362 pub fn negate(expr: Expr) -> Self {
363 Self::Not(Box::new(expr))
364 }
365
366 pub fn and_expr(self, other: Expr) -> Self {
367 if self == other {
368 return self;
369 }
370 match self {
371 Self::And(mut parts) => {
372 if !parts.contains(&other) {
373 parts.push(other);
374 }
375 Self::And(parts)
376 }
377 expr => Self::And(vec![expr, other]),
378 }
379 }
380
381 pub fn or_expr(self, other: Expr) -> Self {
382 if self == other {
383 return self;
384 }
385 match self {
386 Self::Or(mut parts) => {
387 if !parts.contains(&other) {
388 parts.push(other);
389 }
390 Self::Or(parts)
391 }
392 expr => Self::Or(vec![expr, other]),
393 }
394 }
395}