Skip to main content

vantage_sql/primitives/
case.rs

1use std::fmt::{Debug, Display};
2
3use vantage_expressions::{Expression, Expressive, ExpressiveEnum};
4
5/// SQL CASE expression: `CASE WHEN cond THEN val ... ELSE val END`.
6///
7/// # Examples
8///
9/// ```ignore
10/// Case::new()
11///     .when(sqlite_expr!("{} >= {}", (Identifier::new("salary")), 100000.0f64), sqlite_expr!("{}", "senior"))
12///     .when(sqlite_expr!("{} >= {}", (Identifier::new("salary")), 60000.0f64), sqlite_expr!("{}", "mid"))
13///     .else_(sqlite_expr!("{}", "intern"))
14///     .as_alias("band")
15/// ```
16#[derive(Debug, Clone)]
17pub struct Case<T: Debug + Display + Clone> {
18    branches: Vec<(Expression<T>, Expression<T>)>,
19    else_branch: Option<Expression<T>>,
20}
21
22impl<T: Debug + Display + Clone> Default for Case<T> {
23    fn default() -> Self {
24        Self::new()
25    }
26}
27
28impl<T: Debug + Display + Clone> Case<T> {
29    pub fn new() -> Self {
30        Self {
31            branches: Vec::new(),
32            else_branch: None,
33        }
34    }
35
36    pub fn when(mut self, condition: impl Expressive<T>, then: impl Expressive<T>) -> Self {
37        self.branches.push((condition.expr(), then.expr()));
38        self
39    }
40
41    pub fn else_(mut self, value: impl Expressive<T>) -> Self {
42        self.else_branch = Some(value.expr());
43        self
44    }
45}
46
47impl<T: Debug + Display + Clone> Expressive<T> for Case<T> {
48    fn expr(&self) -> Expression<T> {
49        let mut parts: Vec<Expression<T>> = Vec::new();
50        for (cond, then) in &self.branches {
51            parts.push(Expression::new(
52                " WHEN {} THEN {}",
53                vec![
54                    ExpressiveEnum::Nested(cond.clone()),
55                    ExpressiveEnum::Nested(then.clone()),
56                ],
57            ));
58        }
59
60        let branches_expr = Expression::from_vec(parts, "");
61
62        match &self.else_branch {
63            Some(else_val) => Expression::new(
64                "CASE{} ELSE {} END",
65                vec![
66                    ExpressiveEnum::Nested(branches_expr),
67                    ExpressiveEnum::Nested(else_val.clone()),
68                ],
69            ),
70            None => Expression::new("CASE{} END", vec![ExpressiveEnum::Nested(branches_expr)]),
71        }
72    }
73}