dbkit_core/
expr.rs

1use std::marker::PhantomData;
2
3use crate::schema::{Column, ColumnRef};
4
5#[derive(Debug, Clone, PartialEq)]
6pub enum Value {
7    Null,
8    Bool(bool),
9    I16(i16),
10    I32(i32),
11    I64(i64),
12    F32(f32),
13    F64(f64),
14    String(String),
15    Array(Vec<String>),
16    Json(serde_json::Value),
17    Uuid(uuid::Uuid),
18    DateTime(chrono::NaiveDateTime),
19    Date(chrono::NaiveDate),
20    Time(chrono::NaiveTime),
21}
22
23pub trait ColumnValue<T> {
24    fn into_value(self) -> Option<Value>;
25}
26
27impl<T> ColumnValue<T> for T
28where
29    T: Into<Value>,
30{
31    fn into_value(self) -> Option<Value> {
32        Some(self.into())
33    }
34}
35
36impl<T> ColumnValue<T> for Option<T>
37where
38    T: Into<Value>,
39{
40    fn into_value(self) -> Option<Value> {
41        self.map(Into::into)
42    }
43}
44
45impl ColumnValue<String> for &str {
46    fn into_value(self) -> Option<Value> {
47        Some(Value::String(self.to_string()))
48    }
49}
50
51impl<T> ColumnValue<T> for &T
52where
53    T: Clone + Into<Value>,
54{
55    fn into_value(self) -> Option<Value> {
56        Some(self.clone().into())
57    }
58}
59
60impl From<bool> for Value {
61    fn from(value: bool) -> Self {
62        Self::Bool(value)
63    }
64}
65
66impl From<i16> for Value {
67    fn from(value: i16) -> Self {
68        Self::I16(value)
69    }
70}
71
72impl From<i32> for Value {
73    fn from(value: i32) -> Self {
74        Self::I32(value)
75    }
76}
77
78impl From<i64> for Value {
79    fn from(value: i64) -> Self {
80        Self::I64(value)
81    }
82}
83
84impl From<f32> for Value {
85    fn from(value: f32) -> Self {
86        Self::F32(value)
87    }
88}
89
90impl From<f64> for Value {
91    fn from(value: f64) -> Self {
92        Self::F64(value)
93    }
94}
95
96impl From<String> for Value {
97    fn from(value: String) -> Self {
98        Self::String(value)
99    }
100}
101
102impl From<&str> for Value {
103    fn from(value: &str) -> Self {
104        Self::String(value.to_string())
105    }
106}
107
108impl From<Vec<String>> for Value {
109    fn from(value: Vec<String>) -> Self {
110        Self::Array(value)
111    }
112}
113
114impl From<serde_json::Value> for Value {
115    fn from(value: serde_json::Value) -> Self {
116        Self::Json(value)
117    }
118}
119
120impl From<uuid::Uuid> for Value {
121    fn from(value: uuid::Uuid) -> Self {
122        Self::Uuid(value)
123    }
124}
125
126impl From<chrono::NaiveDateTime> for Value {
127    fn from(value: chrono::NaiveDateTime) -> Self {
128        Self::DateTime(value)
129    }
130}
131
132impl From<chrono::NaiveDate> for Value {
133    fn from(value: chrono::NaiveDate) -> Self {
134        Self::Date(value)
135    }
136}
137
138impl From<chrono::NaiveTime> for Value {
139    fn from(value: chrono::NaiveTime) -> Self {
140        Self::Time(value)
141    }
142}
143
144impl<T> From<Option<T>> for Value
145where
146    T: Into<Value>,
147{
148    fn from(value: Option<T>) -> Self {
149        match value {
150            Some(v) => v.into(),
151            None => Self::Null,
152        }
153    }
154}
155
156#[derive(Debug, Clone, Copy)]
157pub enum BinaryOp {
158    Eq,
159    Ne,
160    Lt,
161    Le,
162    Gt,
163    Ge,
164}
165
166#[derive(Debug, Clone, Copy)]
167pub enum BoolOp {
168    And,
169    Or,
170}
171
172#[derive(Debug, Clone, Copy)]
173pub enum UnaryOp {
174    Not,
175}
176
177#[derive(Debug, Clone)]
178pub enum ExprNode {
179    Column(ColumnRef),
180    Value(Value),
181    Func {
182        name: &'static str,
183        args: Vec<ExprNode>,
184    },
185    Binary {
186        left: Box<ExprNode>,
187        op: BinaryOp,
188        right: Box<ExprNode>,
189    },
190    Bool {
191        left: Box<ExprNode>,
192        op: BoolOp,
193        right: Box<ExprNode>,
194    },
195    Unary {
196        op: UnaryOp,
197        expr: Box<ExprNode>,
198    },
199    In {
200        expr: Box<ExprNode>,
201        values: Vec<Value>,
202    },
203    IsNull {
204        expr: Box<ExprNode>,
205        negated: bool,
206    },
207    Like {
208        expr: Box<ExprNode>,
209        pattern: Value,
210        case_insensitive: bool,
211    },
212}
213
214#[derive(Debug, Clone)]
215pub struct Expr<T> {
216    pub node: ExprNode,
217    _marker: PhantomData<T>,
218}
219
220impl<T> Expr<T> {
221    pub fn new(node: ExprNode) -> Self {
222        Self {
223            node,
224            _marker: PhantomData,
225        }
226    }
227}
228
229pub trait IntoExpr<T> {
230    fn into_expr(self) -> Expr<T>;
231}
232
233impl<T> IntoExpr<T> for Expr<T> {
234    fn into_expr(self) -> Expr<T> {
235        self
236    }
237}
238
239impl<M, T> IntoExpr<T> for Column<M, T> {
240    fn into_expr(self) -> Expr<T> {
241        Expr::new(ExprNode::Column(self.as_ref()))
242    }
243}
244
245impl IntoExpr<String> for String {
246    fn into_expr(self) -> Expr<String> {
247        Expr::new(ExprNode::Value(Value::String(self)))
248    }
249}
250
251impl IntoExpr<String> for &str {
252    fn into_expr(self) -> Expr<String> {
253        Expr::new(ExprNode::Value(Value::String(self.to_string())))
254    }
255}
256
257impl IntoExpr<bool> for bool {
258    fn into_expr(self) -> Expr<bool> {
259        Expr::new(ExprNode::Value(Value::Bool(self)))
260    }
261}
262
263impl IntoExpr<i16> for i16 {
264    fn into_expr(self) -> Expr<i16> {
265        Expr::new(ExprNode::Value(Value::I16(self)))
266    }
267}
268
269impl IntoExpr<i32> for i32 {
270    fn into_expr(self) -> Expr<i32> {
271        Expr::new(ExprNode::Value(Value::I32(self)))
272    }
273}
274
275impl IntoExpr<i64> for i64 {
276    fn into_expr(self) -> Expr<i64> {
277        Expr::new(ExprNode::Value(Value::I64(self)))
278    }
279}
280
281impl IntoExpr<f32> for f32 {
282    fn into_expr(self) -> Expr<f32> {
283        Expr::new(ExprNode::Value(Value::F32(self)))
284    }
285}
286
287impl IntoExpr<f64> for f64 {
288    fn into_expr(self) -> Expr<f64> {
289        Expr::new(ExprNode::Value(Value::F64(self)))
290    }
291}
292
293impl IntoExpr<uuid::Uuid> for uuid::Uuid {
294    fn into_expr(self) -> Expr<uuid::Uuid> {
295        Expr::new(ExprNode::Value(Value::Uuid(self)))
296    }
297}
298
299impl IntoExpr<chrono::NaiveDateTime> for chrono::NaiveDateTime {
300    fn into_expr(self) -> Expr<chrono::NaiveDateTime> {
301        Expr::new(ExprNode::Value(Value::DateTime(self)))
302    }
303}
304
305impl IntoExpr<chrono::NaiveDate> for chrono::NaiveDate {
306    fn into_expr(self) -> Expr<chrono::NaiveDate> {
307        Expr::new(ExprNode::Value(Value::Date(self)))
308    }
309}
310
311impl IntoExpr<chrono::NaiveTime> for chrono::NaiveTime {
312    fn into_expr(self) -> Expr<chrono::NaiveTime> {
313        Expr::new(ExprNode::Value(Value::Time(self)))
314    }
315}
316
317impl IntoExpr<Vec<String>> for Vec<String> {
318    fn into_expr(self) -> Expr<Vec<String>> {
319        Expr::new(ExprNode::Value(Value::Array(self)))
320    }
321}
322
323impl IntoExpr<serde_json::Value> for serde_json::Value {
324    fn into_expr(self) -> Expr<serde_json::Value> {
325        Expr::new(ExprNode::Value(Value::Json(self)))
326    }
327}
328
329impl<T> Expr<T>
330where
331    T: 'static,
332{
333    pub fn eq<V>(self, value: V) -> Expr<bool>
334    where
335        V: ColumnValue<T>,
336    {
337        match value.into_value() {
338            Some(value) => Expr::new(ExprNode::Binary {
339                left: Box::new(self.node),
340                op: BinaryOp::Eq,
341                right: Box::new(ExprNode::Value(value)),
342            }),
343            None => Expr::new(ExprNode::IsNull {
344                expr: Box::new(self.node),
345                negated: false,
346            }),
347        }
348    }
349
350    pub fn ne<V>(self, value: V) -> Expr<bool>
351    where
352        V: ColumnValue<T>,
353    {
354        match value.into_value() {
355            Some(value) => Expr::new(ExprNode::Binary {
356                left: Box::new(self.node),
357                op: BinaryOp::Ne,
358                right: Box::new(ExprNode::Value(value)),
359            }),
360            None => Expr::new(ExprNode::IsNull {
361                expr: Box::new(self.node),
362                negated: true,
363            }),
364        }
365    }
366
367    pub fn lt<V>(self, value: V) -> Expr<bool>
368    where
369        V: ColumnValue<T>,
370    {
371        Expr::new(ExprNode::Binary {
372            left: Box::new(self.node),
373            op: BinaryOp::Lt,
374            right: Box::new(ExprNode::Value(value.into_value().unwrap_or(Value::Null))),
375        })
376    }
377
378    pub fn le<V>(self, value: V) -> Expr<bool>
379    where
380        V: ColumnValue<T>,
381    {
382        Expr::new(ExprNode::Binary {
383            left: Box::new(self.node),
384            op: BinaryOp::Le,
385            right: Box::new(ExprNode::Value(value.into_value().unwrap_or(Value::Null))),
386        })
387    }
388
389    pub fn gt<V>(self, value: V) -> Expr<bool>
390    where
391        V: ColumnValue<T>,
392    {
393        Expr::new(ExprNode::Binary {
394            left: Box::new(self.node),
395            op: BinaryOp::Gt,
396            right: Box::new(ExprNode::Value(value.into_value().unwrap_or(Value::Null))),
397        })
398    }
399
400    pub fn ge<V>(self, value: V) -> Expr<bool>
401    where
402        V: ColumnValue<T>,
403    {
404        Expr::new(ExprNode::Binary {
405            left: Box::new(self.node),
406            op: BinaryOp::Ge,
407            right: Box::new(ExprNode::Value(value.into_value().unwrap_or(Value::Null))),
408        })
409    }
410
411    pub fn between<L, U>(self, low: L, high: U) -> Expr<bool>
412    where
413        L: ColumnValue<T>,
414        U: ColumnValue<T>,
415    {
416        let low_value = low.into_value().unwrap_or(Value::Null);
417        let high_value = high.into_value().unwrap_or(Value::Null);
418        let node = self.node;
419        let left = ExprNode::Binary {
420            left: Box::new(node.clone()),
421            op: BinaryOp::Ge,
422            right: Box::new(ExprNode::Value(low_value)),
423        };
424        let right = ExprNode::Binary {
425            left: Box::new(node),
426            op: BinaryOp::Le,
427            right: Box::new(ExprNode::Value(high_value)),
428        };
429        Expr::new(ExprNode::Bool {
430            left: Box::new(left),
431            op: BoolOp::And,
432            right: Box::new(right),
433        })
434    }
435
436    pub fn like<V>(self, pattern: V) -> Expr<bool>
437    where
438        V: ColumnValue<T>,
439    {
440        Expr::new(ExprNode::Like {
441            expr: Box::new(self.node),
442            pattern: pattern.into_value().unwrap_or(Value::Null),
443            case_insensitive: false,
444        })
445    }
446
447    pub fn ilike<V>(self, pattern: V) -> Expr<bool>
448    where
449        V: ColumnValue<T>,
450    {
451        Expr::new(ExprNode::Like {
452            expr: Box::new(self.node),
453            pattern: pattern.into_value().unwrap_or(Value::Null),
454            case_insensitive: true,
455        })
456    }
457
458    pub fn is_null(self) -> Expr<bool> {
459        Expr::new(ExprNode::IsNull {
460            expr: Box::new(self.node),
461            negated: false,
462        })
463    }
464
465    pub fn is_not_null(self) -> Expr<bool> {
466        Expr::new(ExprNode::IsNull {
467            expr: Box::new(self.node),
468            negated: true,
469        })
470    }
471
472    pub fn in_<I, V>(self, values: I) -> Expr<bool>
473    where
474        I: IntoIterator<Item = V>,
475        V: ColumnValue<T>,
476    {
477        let mut binds = Vec::new();
478        for value in values {
479            if let Some(value) = value.into_value() {
480                binds.push(value);
481            }
482        }
483        Expr::new(ExprNode::In {
484            expr: Box::new(self.node),
485            values: binds,
486        })
487    }
488}
489
490impl Expr<bool> {
491    pub fn and(self, other: Expr<bool>) -> Expr<bool> {
492        Expr::new(ExprNode::Bool {
493            left: Box::new(self.node),
494            op: BoolOp::And,
495            right: Box::new(other.node),
496        })
497    }
498
499    pub fn or(self, other: Expr<bool>) -> Expr<bool> {
500        Expr::new(ExprNode::Bool {
501            left: Box::new(self.node),
502            op: BoolOp::Or,
503            right: Box::new(other.node),
504        })
505    }
506
507    pub fn not(self) -> Expr<bool> {
508        Expr::new(ExprNode::Unary {
509            op: UnaryOp::Not,
510            expr: Box::new(self.node),
511        })
512    }
513}
514
515impl<M, T> Column<M, T>
516where
517    T: 'static,
518{
519    pub fn eq<V>(self, value: V) -> Expr<bool>
520    where
521        V: ColumnValue<T>,
522    {
523        match value.into_value() {
524            Some(value) => Expr::new(ExprNode::Binary {
525                left: Box::new(ExprNode::Column(self.as_ref())),
526                op: BinaryOp::Eq,
527                right: Box::new(ExprNode::Value(value)),
528            }),
529            None => Expr::new(ExprNode::IsNull {
530                expr: Box::new(ExprNode::Column(self.as_ref())),
531                negated: false,
532            }),
533        }
534    }
535
536    pub fn eq_col<M2>(self, other: Column<M2, T>) -> Expr<bool> {
537        Expr::new(ExprNode::Binary {
538            left: Box::new(ExprNode::Column(self.as_ref())),
539            op: BinaryOp::Eq,
540            right: Box::new(ExprNode::Column(other.as_ref())),
541        })
542    }
543
544    pub fn ne<V>(self, value: V) -> Expr<bool>
545    where
546        V: ColumnValue<T>,
547    {
548        match value.into_value() {
549            Some(value) => Expr::new(ExprNode::Binary {
550                left: Box::new(ExprNode::Column(self.as_ref())),
551                op: BinaryOp::Ne,
552                right: Box::new(ExprNode::Value(value)),
553            }),
554            None => Expr::new(ExprNode::IsNull {
555                expr: Box::new(ExprNode::Column(self.as_ref())),
556                negated: true,
557            }),
558        }
559    }
560
561    pub fn lt<V>(self, value: V) -> Expr<bool>
562    where
563        V: Into<Value>,
564    {
565        Expr::new(ExprNode::Binary {
566            left: Box::new(ExprNode::Column(self.as_ref())),
567            op: BinaryOp::Lt,
568            right: Box::new(ExprNode::Value(value.into())),
569        })
570    }
571
572    pub fn le<V>(self, value: V) -> Expr<bool>
573    where
574        V: Into<Value>,
575    {
576        Expr::new(ExprNode::Binary {
577            left: Box::new(ExprNode::Column(self.as_ref())),
578            op: BinaryOp::Le,
579            right: Box::new(ExprNode::Value(value.into())),
580        })
581    }
582
583    pub fn gt<V>(self, value: V) -> Expr<bool>
584    where
585        V: Into<Value>,
586    {
587        Expr::new(ExprNode::Binary {
588            left: Box::new(ExprNode::Column(self.as_ref())),
589            op: BinaryOp::Gt,
590            right: Box::new(ExprNode::Value(value.into())),
591        })
592    }
593
594    pub fn ge<V>(self, value: V) -> Expr<bool>
595    where
596        V: Into<Value>,
597    {
598        Expr::new(ExprNode::Binary {
599            left: Box::new(ExprNode::Column(self.as_ref())),
600            op: BinaryOp::Ge,
601            right: Box::new(ExprNode::Value(value.into())),
602        })
603    }
604
605    pub fn between<L, U>(self, low: L, high: U) -> Expr<bool>
606    where
607        L: Into<Value>,
608        U: Into<Value>,
609    {
610        let left = ExprNode::Binary {
611            left: Box::new(ExprNode::Column(self.as_ref())),
612            op: BinaryOp::Ge,
613            right: Box::new(ExprNode::Value(low.into())),
614        };
615        let right = ExprNode::Binary {
616            left: Box::new(ExprNode::Column(self.as_ref())),
617            op: BinaryOp::Le,
618            right: Box::new(ExprNode::Value(high.into())),
619        };
620        Expr::new(ExprNode::Bool {
621            left: Box::new(left),
622            op: BoolOp::And,
623            right: Box::new(right),
624        })
625    }
626
627    pub fn like<V>(self, pattern: V) -> Expr<bool>
628    where
629        V: Into<Value>,
630    {
631        Expr::new(ExprNode::Like {
632            expr: Box::new(ExprNode::Column(self.as_ref())),
633            pattern: pattern.into(),
634            case_insensitive: false,
635        })
636    }
637
638    pub fn ilike<V>(self, pattern: V) -> Expr<bool>
639    where
640        V: Into<Value>,
641    {
642        Expr::new(ExprNode::Like {
643            expr: Box::new(ExprNode::Column(self.as_ref())),
644            pattern: pattern.into(),
645            case_insensitive: true,
646        })
647    }
648
649    pub fn in_<I, V>(self, values: I) -> Expr<bool>
650    where
651        I: IntoIterator<Item = V>,
652        V: Into<Value>,
653    {
654        Expr::new(ExprNode::In {
655            expr: Box::new(ExprNode::Column(self.as_ref())),
656            values: values.into_iter().map(Into::into).collect(),
657        })
658    }
659
660    pub fn is_null(self) -> Expr<bool> {
661        Expr::new(ExprNode::IsNull {
662            expr: Box::new(ExprNode::Column(self.as_ref())),
663            negated: false,
664        })
665    }
666
667    pub fn is_not_null(self) -> Expr<bool> {
668        Expr::new(ExprNode::IsNull {
669            expr: Box::new(ExprNode::Column(self.as_ref())),
670            negated: true,
671        })
672    }
673}
674
675#[derive(Debug, Clone, Copy)]
676pub enum ConditionKind {
677    Any,
678    All,
679}
680
681#[derive(Debug, Clone)]
682pub struct Condition {
683    kind: ConditionKind,
684    exprs: Vec<Expr<bool>>,
685}
686
687impl Condition {
688    pub fn any() -> Self {
689        Self {
690            kind: ConditionKind::Any,
691            exprs: Vec::new(),
692        }
693    }
694
695    pub fn all() -> Self {
696        Self {
697            kind: ConditionKind::All,
698            exprs: Vec::new(),
699        }
700    }
701
702    pub fn add(mut self, expr: Expr<bool>) -> Self {
703        self.exprs.push(expr);
704        self
705    }
706
707    pub fn into_expr(self) -> Option<Expr<bool>> {
708        let mut iter = self.exprs.into_iter();
709        let first = iter.next()?;
710        Some(iter.fold(first, |acc, expr| match self.kind {
711            ConditionKind::Any => acc.or(expr),
712            ConditionKind::All => acc.and(expr),
713        }))
714    }
715}