Skip to main content

teaql_core/
expr.rs

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}