gluesql_core/ast_builder/expr/
case.rs

1use super::ExprNode;
2
3impl<'a> ExprNode<'a> {
4    pub fn case(self) -> CaseNode<'a> {
5        CaseNode {
6            operand: Some(Box::new(self)),
7        }
8    }
9}
10
11pub fn case() -> CaseNode<'static> {
12    CaseNode { operand: None }
13}
14
15#[derive(Clone, Debug)]
16pub struct CaseNode<'a> {
17    operand: Option<Box<ExprNode<'a>>>,
18}
19
20impl<'a> CaseNode<'a> {
21    pub fn when_then<W: Into<ExprNode<'a>>, T: Into<ExprNode<'a>>>(
22        self,
23        when: W,
24        then: T,
25    ) -> WhenThenNode<'a> {
26        WhenThenNode {
27            prev_node: self,
28            when_then: vec![(when.into(), then.into())],
29        }
30    }
31}
32
33#[derive(Clone, Debug)]
34pub struct WhenThenNode<'a> {
35    prev_node: CaseNode<'a>,
36    when_then: Vec<(ExprNode<'a>, ExprNode<'a>)>,
37}
38
39impl<'a> WhenThenNode<'a> {
40    pub fn when_then<W: Into<ExprNode<'a>>, T: Into<ExprNode<'a>>>(
41        mut self,
42        when: W,
43        then: T,
44    ) -> Self {
45        self.when_then.push((when.into(), then.into()));
46        self
47    }
48
49    pub fn or_else<T: Into<ExprNode<'a>>>(self, else_result: T) -> ExprNode<'a> {
50        ExprNode::Case {
51            operand: self.prev_node.operand,
52            when_then: self.when_then,
53            else_result: Some(Box::new(else_result.into())),
54        }
55    }
56
57    pub fn end(self) -> ExprNode<'a> {
58        ExprNode::Case {
59            operand: self.prev_node.operand,
60            when_then: self.when_then,
61            else_result: None,
62        }
63    }
64}
65
66#[cfg(test)]
67mod tests {
68    use crate::ast_builder::{case, col, num, test_expr, text};
69
70    #[test]
71    fn case_with_operand() {
72        let actual = col("id")
73            .case()
74            .when_then(num(1), text("a"))
75            .when_then(2, text("b"))
76            .or_else(text("c"));
77        let expected = "
78            CASE id
79              WHEN 1 THEN 'a'
80              WHEN 2 THEN 'b'
81              ELSE 'c'
82            END
83            ";
84        test_expr(actual, expected);
85
86        let actual = col("id")
87            .gt(10)
88            .case()
89            .when_then(true, text("a"))
90            .when_then(false, text("b"))
91            .end();
92        let expected = "
93            CASE id > 10
94              WHEN True THEN 'a'
95              WHEN False THEN 'b'
96            END
97            ";
98        test_expr(actual, expected);
99    }
100
101    #[test]
102    fn case_without_operand() {
103        let actual = case()
104            .when_then(
105                "City IS NULL",
106                case()
107                    .when_then("Country IS NULL", text("weird"))
108                    .or_else("Country"),
109            )
110            .or_else("City");
111        let expected = r#"
112            CASE
113              WHEN City IS NULL THEN CASE WHEN Country IS NULL THEN 'weird'
114                                          ELSE Country
115                                          END
116              ELSE City
117            END
118            "#;
119        test_expr(actual, expected);
120    }
121}