sqlparser_mysql/base/
order.rs

1use std::fmt;
2use std::fmt::{Display, Formatter};
3use std::str;
4
5use nom::branch::alt;
6use nom::bytes::complete::tag_no_case;
7use nom::character::complete::{multispace0, multispace1};
8use nom::combinator::{map, opt};
9use nom::multi::many0;
10use nom::sequence::{preceded, tuple};
11use nom::IResult;
12
13use base::column::Column;
14use base::error::ParseSQLError;
15use base::{CommonParser, DisplayUtil};
16
17#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
18pub struct OrderClause {
19    pub columns: Vec<(Column, OrderType)>, // TODO(malte): can this be an arbitrary expr?
20}
21
22impl OrderClause {
23    // Parse ORDER BY clause
24    pub fn parse(i: &str) -> IResult<&str, OrderClause, ParseSQLError<&str>> {
25        let (remaining_input, (_, _, _, _, _, columns)) = tuple((
26            multispace0,
27            tag_no_case("ORDER"),
28            multispace1,
29            tag_no_case("BY"),
30            multispace1,
31            many0(Self::order_expr),
32        ))(i)?;
33
34        Ok((remaining_input, OrderClause { columns }))
35    }
36
37    fn order_expr(i: &str) -> IResult<&str, (Column, OrderType), ParseSQLError<&str>> {
38        let (remaining_input, (field_name, ordering, _)) = tuple((
39            Column::without_alias,
40            opt(preceded(multispace0, OrderType::parse)),
41            opt(CommonParser::ws_sep_comma),
42        ))(i)?;
43
44        Ok((
45            remaining_input,
46            (field_name, ordering.unwrap_or(OrderType::Asc)),
47        ))
48    }
49}
50
51impl fmt::Display for OrderClause {
52    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
53        write!(f, "ORDER BY ")?;
54        write!(
55            f,
56            "{}",
57            self.columns
58                .iter()
59                .map(|(c, o)| format!("{} {}", DisplayUtil::escape_if_keyword(&c.name), o))
60                .collect::<Vec<_>>()
61                .join(", ")
62        )
63    }
64}
65
66/// parse `[ASC | DESC]`
67#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
68pub enum OrderType {
69    Asc,
70    Desc,
71}
72
73impl OrderType {
74    pub fn parse(i: &str) -> IResult<&str, OrderType, ParseSQLError<&str>> {
75        alt((
76            map(tag_no_case("DESC"), |_| OrderType::Desc),
77            map(tag_no_case("ASC"), |_| OrderType::Asc),
78        ))(i)
79    }
80}
81
82impl Display for OrderType {
83    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
84        match *self {
85            OrderType::Asc => write!(f, "ASC"),
86            OrderType::Desc => write!(f, "DESC"),
87        }
88    }
89}
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94
95    #[test]
96    fn parse_order_clause() {
97        let str1 = "order by name desc";
98        let str2 = "order by name asc, age desc";
99        let str3 = "order by name";
100
101        let expected_ord1 = OrderClause {
102            columns: vec![("name".into(), OrderType::Desc)],
103        };
104        let expected_ord2 = OrderClause {
105            columns: vec![
106                ("name".into(), OrderType::Asc),
107                ("age".into(), OrderType::Desc),
108            ],
109        };
110        let expected_ord3 = OrderClause {
111            columns: vec![("name".into(), OrderType::Asc)],
112        };
113
114        let res1 = OrderClause::parse(str1);
115        let res2 = OrderClause::parse(str2);
116        let res3 = OrderClause::parse(str3);
117        assert_eq!(res1.unwrap().1, expected_ord1);
118        assert_eq!(res2.unwrap().1, expected_ord2);
119        assert_eq!(res3.unwrap().1, expected_ord3);
120    }
121
122    #[test]
123    fn parse_order_type() {
124        let str1 = "aSc";
125        let res1 = OrderType::parse(str1);
126        assert!(res1.is_ok());
127        assert_eq!(res1.unwrap().1, OrderType::Asc);
128
129        let str2 = "desc";
130        let res2 = OrderType::parse(str2);
131        assert!(res2.is_ok());
132        assert_eq!(res2.unwrap().1, OrderType::Desc);
133    }
134}