1use std::fmt;
2
3use column::Column;
4use common::{column_identifier_no_alias, literal, Literal};
5use condition::{condition_expr, ConditionExpression};
6
7use nom::bytes::complete::tag_no_case;
8use nom::character::complete::multispace0;
9use nom::combinator::opt;
10use nom::sequence::{delimited, terminated, tuple};
11use nom::IResult;
12
13#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
14pub enum ColumnOrLiteral {
15 Column(Column),
16 Literal(Literal),
17}
18
19impl fmt::Display for ColumnOrLiteral {
20 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21 match *self {
22 ColumnOrLiteral::Column(ref c) => write!(f, "{}", c)?,
23 ColumnOrLiteral::Literal(ref l) => write!(f, "{}", l.to_string())?,
24 }
25 Ok(())
26 }
27}
28
29#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
30pub struct CaseWhenExpression {
31 pub condition: ConditionExpression,
32 pub then_expr: ColumnOrLiteral,
33 pub else_expr: Option<ColumnOrLiteral>,
34}
35
36impl fmt::Display for CaseWhenExpression {
37 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
38 write!(f, "CASE WHEN {} THEN {}", self.condition, self.then_expr)?;
39 if let Some(ref expr) = self.else_expr {
40 write!(f, " ELSE {}", expr)?;
41 }
42 Ok(())
43 }
44}
45
46pub fn case_when_column(i: &[u8]) -> IResult<&[u8], CaseWhenExpression> {
47 let (remaining_input, (_, _, condition, _, _, _, column, _, else_val, _)) = tuple((
48 tag_no_case("case when"),
49 multispace0,
50 condition_expr,
51 multispace0,
52 tag_no_case("then"),
53 multispace0,
54 column_identifier_no_alias,
55 multispace0,
56 opt(delimited(
57 terminated(tag_no_case("else"), multispace0),
58 literal,
59 multispace0,
60 )),
61 tag_no_case("end"),
62 ))(i)?;
63
64 let then_expr = ColumnOrLiteral::Column(column);
65 let else_expr = else_val.map(|v| ColumnOrLiteral::Literal(v));
66
67 Ok((
68 remaining_input,
69 CaseWhenExpression {
70 condition,
71 then_expr,
72 else_expr,
73 },
74 ))
75}