nom-sql 0.0.11

A SQL parser written using nom.
Documentation
use nom::character::complete::multispace0;
use std::{fmt, str};

use common::{statement_terminator, table_list};
use keywords::escape_if_keyword;
use nom::bytes::complete::tag_no_case;
use nom::combinator::opt;
use nom::sequence::{delimited, tuple};
use nom::IResult;
use table::Table;

#[derive(Clone, Debug, Default, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct DropTableStatement {
    pub tables: Vec<Table>,
    pub if_exists: bool,
}

impl fmt::Display for DropTableStatement {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "DROP TABLE ")?;
        if self.if_exists {
            write!(f, "IF EXISTS ")?;
        }
        let ts = self
            .tables
            .iter()
            .map(|t| escape_if_keyword(&t.name))
            .collect::<Vec<_>>()
            .join(", ");
        write!(f, "{}", ts)?;
        Ok(())
    }
}

pub fn drop_table(i: &[u8]) -> IResult<&[u8], DropTableStatement> {
    let (remaining_input, (_, opt_if_exists, _, tables, _, _, _, _)) = tuple((
        tag_no_case("drop table"),
        opt(delimited(
            multispace0,
            tag_no_case("if exists"),
            multispace0,
        )),
        multispace0,
        table_list,
        multispace0,
        opt(delimited(
            multispace0,
            tag_no_case("restricted"),
            multispace0,
        )),
        opt(delimited(multispace0, tag_no_case("cascade"), multispace0)),
        statement_terminator,
    ))(i)?;

    Ok((
        remaining_input,
        DropTableStatement {
            tables,
            if_exists: opt_if_exists.is_some(),
        },
    ))
}

#[cfg(test)]
mod tests {
    use super::*;
    use table::Table;

    #[test]
    fn simple_drop_table() {
        let qstring = "DROP TABLE users;";
        let res = drop_table(qstring.as_bytes());
        assert_eq!(
            res.unwrap().1,
            DropTableStatement {
                tables: vec![Table::from("users")],
                if_exists: false,
            }
        );
    }

    #[test]
    fn format_drop_table() {
        let qstring = "DROP TABLE IF EXISTS users,posts;";
        let expected = "DROP TABLE IF EXISTS users, posts";
        let res = drop_table(qstring.as_bytes());
        assert_eq!(format!("{}", res.unwrap().1), expected);
    }
}