gluesql_core/ast_builder/expr/
case.rs1use 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}