nom-sql 0.0.11

A SQL parser written using nom.
Documentation
use std::fmt;

use column::Column;
use common::{column_identifier_no_alias, literal, Literal};
use condition::{condition_expr, ConditionExpression};

use nom::bytes::complete::tag_no_case;
use nom::character::complete::multispace0;
use nom::combinator::opt;
use nom::sequence::{delimited, terminated, tuple};
use nom::IResult;

#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub enum ColumnOrLiteral {
    Column(Column),
    Literal(Literal),
}

impl fmt::Display for ColumnOrLiteral {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ColumnOrLiteral::Column(ref c) => write!(f, "{}", c)?,
            ColumnOrLiteral::Literal(ref l) => write!(f, "{}", l.to_string())?,
        }
        Ok(())
    }
}

#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct CaseWhenExpression {
    pub condition: ConditionExpression,
    pub then_expr: ColumnOrLiteral,
    pub else_expr: Option<ColumnOrLiteral>,
}

impl fmt::Display for CaseWhenExpression {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "CASE WHEN {} THEN {}", self.condition, self.then_expr)?;
        if let Some(ref expr) = self.else_expr {
            write!(f, " ELSE {}", expr)?;
        }
        Ok(())
    }
}

pub fn case_when_column(i: &[u8]) -> IResult<&[u8], CaseWhenExpression> {
    let (remaining_input, (_, _, condition, _, _, _, column, _, else_val, _)) = tuple((
        tag_no_case("case when"),
        multispace0,
        condition_expr,
        multispace0,
        tag_no_case("then"),
        multispace0,
        column_identifier_no_alias,
        multispace0,
        opt(delimited(
            terminated(tag_no_case("else"), multispace0),
            literal,
            multispace0,
        )),
        tag_no_case("end"),
    ))(i)?;

    let then_expr = ColumnOrLiteral::Column(column);
    let else_expr = else_val.map(|v| ColumnOrLiteral::Literal(v));

    Ok((
        remaining_input,
        CaseWhenExpression {
            condition,
            then_expr,
            else_expr,
        },
    ))
}