nom_sql/
order.rs

1use nom::character::complete::{multispace0, multispace1};
2use std::fmt;
3use std::str;
4
5use column::Column;
6use common::{column_identifier_no_alias, ws_sep_comma};
7use keywords::escape_if_keyword;
8use nom::branch::alt;
9use nom::bytes::complete::tag_no_case;
10use nom::combinator::{map, opt};
11use nom::multi::many0;
12use nom::sequence::{preceded, tuple};
13use nom::IResult;
14
15#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
16pub enum OrderType {
17    OrderAscending,
18    OrderDescending,
19}
20
21impl fmt::Display for OrderType {
22    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23        match *self {
24            OrderType::OrderAscending => write!(f, "ASC"),
25            OrderType::OrderDescending => write!(f, "DESC"),
26        }
27    }
28}
29
30#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
31pub struct OrderClause {
32    pub columns: Vec<(Column, OrderType)>, // TODO(malte): can this be an arbitrary expr?
33}
34
35impl fmt::Display for OrderClause {
36    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
37        write!(f, "ORDER BY ")?;
38        write!(
39            f,
40            "{}",
41            self.columns
42                .iter()
43                .map(|&(ref c, ref o)| format!("{} {}", escape_if_keyword(&c.name), o))
44                .collect::<Vec<_>>()
45                .join(", ")
46        )
47    }
48}
49
50pub fn order_type(i: &[u8]) -> IResult<&[u8], OrderType> {
51    alt((
52        map(tag_no_case("desc"), |_| OrderType::OrderDescending),
53        map(tag_no_case("asc"), |_| OrderType::OrderAscending),
54    ))(i)
55}
56
57fn order_expr(i: &[u8]) -> IResult<&[u8], (Column, OrderType)> {
58    let (remaining_input, (field_name, ordering, _)) = tuple((
59        column_identifier_no_alias,
60        opt(preceded(multispace0, order_type)),
61        opt(ws_sep_comma),
62    ))(i)?;
63
64    Ok((
65        remaining_input,
66        (field_name, ordering.unwrap_or(OrderType::OrderAscending)),
67    ))
68}
69
70// Parse ORDER BY clause
71pub fn order_clause(i: &[u8]) -> IResult<&[u8], OrderClause> {
72    let (remaining_input, (_, _, _, columns)) = tuple((
73        multispace0,
74        tag_no_case("order by"),
75        multispace1,
76        many0(order_expr),
77    ))(i)?;
78
79    Ok((remaining_input, OrderClause { columns }))
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85    use select::selection;
86
87    #[test]
88    fn order_clause() {
89        let qstring1 = "select * from users order by name desc\n";
90        let qstring2 = "select * from users order by name asc, age desc\n";
91        let qstring3 = "select * from users order by name\n";
92
93        let expected_ord1 = OrderClause {
94            columns: vec![("name".into(), OrderType::OrderDescending)],
95        };
96        let expected_ord2 = OrderClause {
97            columns: vec![
98                ("name".into(), OrderType::OrderAscending),
99                ("age".into(), OrderType::OrderDescending),
100            ],
101        };
102        let expected_ord3 = OrderClause {
103            columns: vec![("name".into(), OrderType::OrderAscending)],
104        };
105
106        let res1 = selection(qstring1.as_bytes());
107        let res2 = selection(qstring2.as_bytes());
108        let res3 = selection(qstring3.as_bytes());
109        assert_eq!(res1.unwrap().1.order, Some(expected_ord1));
110        assert_eq!(res2.unwrap().1.order, Some(expected_ord2));
111        assert_eq!(res3.unwrap().1.order, Some(expected_ord3));
112    }
113}