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}