Make SQLOrderByExpr::asc tri-state

i.e. ASC/DESC/unspecified - so that we don't lose information about
source code.

Also don't take any keyword other than ASC/DESC or Comma to mean
'ascending'.
This commit is contained in:
Nickolay Ponomarev 2019-01-13 03:26:33 +03:00
parent 12b9f5aafc
commit 3de2a0952c
3 changed files with 23 additions and 33 deletions

View file

@ -366,21 +366,21 @@ impl ToString for SQLAssignment {
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct SQLOrderByExpr { pub struct SQLOrderByExpr {
pub expr: Box<ASTNode>, pub expr: Box<ASTNode>,
pub asc: bool, pub asc: Option<bool>,
} }
impl SQLOrderByExpr { impl SQLOrderByExpr {
pub fn new(expr: Box<ASTNode>, asc: bool) -> Self { pub fn new(expr: Box<ASTNode>, asc: Option<bool>) -> Self {
SQLOrderByExpr { expr, asc } SQLOrderByExpr { expr, asc }
} }
} }
impl ToString for SQLOrderByExpr { impl ToString for SQLOrderByExpr {
fn to_string(&self) -> String { fn to_string(&self) -> String {
if self.asc { match self.asc {
format!("{} ASC", self.expr.as_ref().to_string()) Some(true) => format!("{} ASC", self.expr.to_string()),
} else { Some(false) => format!("{} DESC", self.expr.to_string()),
format!("{} DESC", self.expr.as_ref().to_string()) None => self.expr.to_string(),
} }
} }
} }

View file

@ -1321,33 +1321,19 @@ impl Parser {
loop { loop {
let expr = self.parse_expr(0)?; let expr = self.parse_expr(0)?;
// look for optional ASC / DESC specifier let asc = if self.parse_keyword("ASC") {
let asc = match self.peek_token() { Some(true)
Some(Token::Keyword(k)) => match k.to_uppercase().as_ref() { } else if self.parse_keyword("DESC") {
"ASC" => { Some(false)
self.next_token(); } else {
true None
}
"DESC" => {
self.next_token();
false
}
_ => true,
},
Some(Token::Comma) => true,
_ => true,
}; };
expr_list.push(SQLOrderByExpr::new(Box::new(expr), asc)); expr_list.push(SQLOrderByExpr::new(Box::new(expr), asc));
if let Some(t) = self.peek_token() { if let Some(Token::Comma) = self.peek_token() {
if t == Token::Comma { self.next_token();
self.next_token();
} else {
break;
}
} else { } else {
// EOF
break; break;
} }
} }

View file

@ -230,7 +230,7 @@ fn parse_not_like() {
#[test] #[test]
fn parse_select_order_by() { fn parse_select_order_by() {
let sql = String::from( let sql = String::from(
"SELECT id, fname, lname FROM customer WHERE id < 5 ORDER BY lname ASC, fname DESC", "SELECT id, fname, lname FROM customer WHERE id < 5 ORDER BY lname ASC, fname DESC, id",
); );
match verified(&sql) { match verified(&sql) {
ASTNode::SQLSelect { order_by, .. } => { ASTNode::SQLSelect { order_by, .. } => {
@ -238,11 +238,15 @@ fn parse_select_order_by() {
Some(vec![ Some(vec![
SQLOrderByExpr { SQLOrderByExpr {
expr: Box::new(ASTNode::SQLIdentifier("lname".to_string())), expr: Box::new(ASTNode::SQLIdentifier("lname".to_string())),
asc: true, asc: Some(true),
}, },
SQLOrderByExpr { SQLOrderByExpr {
expr: Box::new(ASTNode::SQLIdentifier("fname".to_string())), expr: Box::new(ASTNode::SQLIdentifier("fname".to_string())),
asc: false, asc: Some(false),
},
SQLOrderByExpr {
expr: Box::new(ASTNode::SQLIdentifier("id".to_string())),
asc: None,
}, },
]), ]),
order_by order_by
@ -266,11 +270,11 @@ fn parse_select_order_by_limit() {
Some(vec![ Some(vec![
SQLOrderByExpr { SQLOrderByExpr {
expr: Box::new(ASTNode::SQLIdentifier("lname".to_string())), expr: Box::new(ASTNode::SQLIdentifier("lname".to_string())),
asc: true, asc: Some(true),
}, },
SQLOrderByExpr { SQLOrderByExpr {
expr: Box::new(ASTNode::SQLIdentifier("fname".to_string())), expr: Box::new(ASTNode::SQLIdentifier("fname".to_string())),
asc: false, asc: Some(false),
}, },
]), ]),
order_by order_by