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)>, }
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
70pub 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}