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 fn column(name: impl Into<String>) -> Self {
70 Self::Column(name.into())
71 }
72
73 pub fn value(value: impl Into<Value>) -> Self {
74 Self::Value(value.into())
75 }
76
77 pub fn function(function: ExprFunction, args: impl IntoIterator<Item = Expr>) -> Self {
78 Self::Function {
79 function,
80 args: args.into_iter().collect(),
81 }
82 }
83
84 pub fn soundex(expr: Expr) -> Self {
85 Self::function(ExprFunction::Soundex, [expr])
86 }
87
88 pub fn gbk(expr: Expr) -> Self {
89 Self::function(ExprFunction::Gbk, [expr])
90 }
91
92 pub fn count_all() -> Self {
93 Self::function(ExprFunction::Count, [])
94 }
95
96 pub fn count_expr(expr: Expr) -> Self {
97 Self::function(ExprFunction::Count, [expr])
98 }
99
100 pub fn sum_expr(expr: Expr) -> Self {
101 Self::function(ExprFunction::Sum, [expr])
102 }
103
104 pub fn avg_expr(expr: Expr) -> Self {
105 Self::function(ExprFunction::Avg, [expr])
106 }
107
108 pub fn min_expr(expr: Expr) -> Self {
109 Self::function(ExprFunction::Min, [expr])
110 }
111
112 pub fn max_expr(expr: Expr) -> Self {
113 Self::function(ExprFunction::Max, [expr])
114 }
115
116 pub fn stddev_expr(expr: Expr) -> Self {
117 Self::function(ExprFunction::Stddev, [expr])
118 }
119
120 pub fn stddev_pop_expr(expr: Expr) -> Self {
121 Self::function(ExprFunction::StddevPop, [expr])
122 }
123
124 pub fn var_samp_expr(expr: Expr) -> Self {
125 Self::function(ExprFunction::VarSamp, [expr])
126 }
127
128 pub fn var_pop_expr(expr: Expr) -> Self {
129 Self::function(ExprFunction::VarPop, [expr])
130 }
131
132 pub fn bit_and_expr(expr: Expr) -> Self {
133 Self::function(ExprFunction::BitAnd, [expr])
134 }
135
136 pub fn bit_or_expr(expr: Expr) -> Self {
137 Self::function(ExprFunction::BitOr, [expr])
138 }
139
140 pub fn bit_xor_expr(expr: Expr) -> Self {
141 Self::function(ExprFunction::BitXor, [expr])
142 }
143
144 pub fn sound_like(column: impl Into<String>, value: impl Into<Value>) -> Self {
145 Self::binary(
146 Self::soundex(Self::column(column)),
147 BinaryOp::Eq,
148 Self::soundex(Self::value(value)),
149 )
150 }
151
152 pub fn eq(column: impl Into<String>, value: impl Into<Value>) -> Self {
153 Self::binary(Self::column(column), BinaryOp::Eq, Self::value(value))
154 }
155
156 pub fn ne(column: impl Into<String>, value: impl Into<Value>) -> Self {
157 Self::binary(Self::column(column), BinaryOp::Ne, Self::value(value))
158 }
159
160 pub fn gt(column: impl Into<String>, value: impl Into<Value>) -> Self {
161 Self::binary(Self::column(column), BinaryOp::Gt, Self::value(value))
162 }
163
164 pub fn gte(column: impl Into<String>, value: impl Into<Value>) -> Self {
165 Self::binary(Self::column(column), BinaryOp::Gte, Self::value(value))
166 }
167
168 pub fn lt(column: impl Into<String>, value: impl Into<Value>) -> Self {
169 Self::binary(Self::column(column), BinaryOp::Lt, Self::value(value))
170 }
171
172 pub fn lte(column: impl Into<String>, value: impl Into<Value>) -> Self {
173 Self::binary(Self::column(column), BinaryOp::Lte, Self::value(value))
174 }
175
176 pub fn like(column: impl Into<String>, pattern: impl Into<String>) -> Self {
177 Self::binary(
178 Self::column(column),
179 BinaryOp::Like,
180 Self::value(pattern.into()),
181 )
182 }
183
184 pub fn not_like(column: impl Into<String>, pattern: impl Into<String>) -> Self {
185 Self::binary(
186 Self::column(column),
187 BinaryOp::NotLike,
188 Self::value(pattern.into()),
189 )
190 }
191
192 pub fn contain(column: impl Into<String>, value: impl Into<String>) -> Self {
193 Self::like(column, format!("%{}%", value.into()))
194 }
195
196 pub fn not_contain(column: impl Into<String>, value: impl Into<String>) -> Self {
197 Self::not_like(column, format!("%{}%", value.into()))
198 }
199
200 pub fn begin_with(column: impl Into<String>, value: impl Into<String>) -> Self {
201 Self::like(column, format!("{}%", value.into()))
202 }
203
204 pub fn not_begin_with(column: impl Into<String>, value: impl Into<String>) -> Self {
205 Self::not_like(column, format!("{}%", value.into()))
206 }
207
208 pub fn end_with(column: impl Into<String>, value: impl Into<String>) -> Self {
209 Self::like(column, format!("%{}", value.into()))
210 }
211
212 pub fn not_end_with(column: impl Into<String>, value: impl Into<String>) -> Self {
213 Self::not_like(column, format!("%{}", value.into()))
214 }
215
216 pub fn binary(left: Expr, op: BinaryOp, right: Expr) -> Self {
217 Self::Binary {
218 left: Box::new(left),
219 op,
220 right: Box::new(right),
221 }
222 }
223
224 pub fn compare_columns(
225 left_column: impl Into<String>,
226 op: BinaryOp,
227 right_column: impl Into<String>,
228 ) -> Self {
229 Self::binary(Self::column(left_column), op, Self::column(right_column))
230 }
231
232 pub fn in_list(column: impl Into<String>, values: impl IntoIterator<Item = Value>) -> Self {
233 Self::binary(
234 Self::column(column),
235 BinaryOp::In,
236 Self::Value(Value::List(values.into_iter().collect())),
237 )
238 }
239
240 pub fn not_in_list(column: impl Into<String>, values: impl IntoIterator<Item = Value>) -> Self {
241 Self::binary(
242 Self::column(column),
243 BinaryOp::NotIn,
244 Self::Value(Value::List(values.into_iter().collect())),
245 )
246 }
247
248 pub fn in_large(column: impl Into<String>, values: impl IntoIterator<Item = Value>) -> Self {
249 Self::binary(
250 Self::column(column),
251 BinaryOp::InLarge,
252 Self::Value(Value::List(values.into_iter().collect())),
253 )
254 }
255
256 pub fn not_in_large(
257 column: impl Into<String>,
258 values: impl IntoIterator<Item = Value>,
259 ) -> Self {
260 Self::binary(
261 Self::column(column),
262 BinaryOp::NotInLarge,
263 Self::Value(Value::List(values.into_iter().collect())),
264 )
265 }
266
267 pub fn in_subquery(
268 column: impl Into<String>,
269 entity: EntityDescriptor,
270 query: SelectQuery,
271 field: impl Into<String>,
272 ) -> Self {
273 Self::subquery(Self::column(column), BinaryOp::In, entity, query, field)
274 }
275
276 pub fn not_in_subquery(
277 column: impl Into<String>,
278 entity: EntityDescriptor,
279 query: SelectQuery,
280 field: impl Into<String>,
281 ) -> Self {
282 Self::subquery(Self::column(column), BinaryOp::NotIn, entity, query, field)
283 }
284
285 pub fn subquery(
286 left: Expr,
287 op: BinaryOp,
288 entity: EntityDescriptor,
289 mut query: SelectQuery,
290 field: impl Into<String>,
291 ) -> Self {
292 query.projection = vec![field.into()];
293 Self::SubQuery {
294 left: Box::new(left),
295 op,
296 entity,
297 query: Box::new(query),
298 }
299 }
300
301 pub fn between(
302 column: impl Into<String>,
303 lower: impl Into<Value>,
304 upper: impl Into<Value>,
305 ) -> Self {
306 Self::Between {
307 expr: Box::new(Self::column(column)),
308 lower: Box::new(Self::value(lower)),
309 upper: Box::new(Self::value(upper)),
310 }
311 }
312
313 pub fn is_null(column: impl Into<String>) -> Self {
314 Self::IsNull(Box::new(Self::column(column)))
315 }
316
317 pub fn is_not_null(column: impl Into<String>) -> Self {
318 Self::IsNotNull(Box::new(Self::column(column)))
319 }
320
321 pub fn and(parts: impl IntoIterator<Item = Expr>) -> Self {
322 Self::And(parts.into_iter().collect())
323 }
324
325 pub fn or(parts: impl IntoIterator<Item = Expr>) -> Self {
326 Self::Or(parts.into_iter().collect())
327 }
328
329 pub fn negate(expr: Expr) -> Self {
330 Self::Not(Box::new(expr))
331 }
332
333 pub fn and_expr(self, other: Expr) -> Self {
334 match self {
335 Self::And(mut parts) => {
336 parts.push(other);
337 Self::And(parts)
338 }
339 expr => Self::And(vec![expr, other]),
340 }
341 }
342
343 pub fn or_expr(self, other: Expr) -> Self {
344 match self {
345 Self::Or(mut parts) => {
346 parts.push(other);
347 Self::Or(parts)
348 }
349 expr => Self::Or(vec![expr, other]),
350 }
351 }
352}