diff --git a/src/sqlast/query.rs b/src/sqlast/query.rs index 69577e55..dbcb0b6b 100644 --- a/src/sqlast/query.rs +++ b/src/sqlast/query.rs @@ -110,6 +110,7 @@ impl ToString for SQLSetOperator { /// to a set operation like `UNION`. #[derive(Debug, Clone, PartialEq)] pub struct SQLSelect { + pub distinct: bool, /// projection expressions pub projection: Vec, /// FROM @@ -127,7 +128,8 @@ pub struct SQLSelect { impl ToString for SQLSelect { fn to_string(&self) -> String { let mut s = format!( - "SELECT {}", + "SELECT{} {}", + if self.distinct { " DISTINCT" } else { "" }, self.projection .iter() .map(|p| p.to_string()) diff --git a/src/sqlparser.rs b/src/sqlparser.rs index a0b70e71..d59048c8 100644 --- a/src/sqlparser.rs +++ b/src/sqlparser.rs @@ -1352,6 +1352,7 @@ impl Parser { /// Parse a restricted `SELECT` statement (no CTEs / `UNION` / `ORDER BY`), /// assuming the initial `SELECT` was already consumed pub fn parse_select(&mut self) -> Result { + let distinct = self.parse_keyword("DISTINCT"); let projection = self.parse_select_list()?; let (relation, joins) = if self.parse_keyword("FROM") { @@ -1381,6 +1382,7 @@ impl Parser { }; Ok(SQLSelect { + distinct, projection, selection, relation, diff --git a/tests/sqlparser_generic.rs b/tests/sqlparser_generic.rs index 9946448f..ea60e6d4 100644 --- a/tests/sqlparser_generic.rs +++ b/tests/sqlparser_generic.rs @@ -50,11 +50,23 @@ fn parse_where_delete_statement() { fn parse_simple_select() { let sql = "SELECT id, fname, lname FROM customer WHERE id = 1 LIMIT 5"; let select = verified_only_select(sql); + assert_eq!(false, select.distinct); assert_eq!(3, select.projection.len()); let select = verified_query(sql); assert_eq!(Some(ASTNode::SQLValue(Value::Long(5))), select.limit); } +#[test] +fn parse_select_distinct() { + let sql = "SELECT DISTINCT name FROM customer"; + let select = verified_only_select(sql); + assert_eq!(true, select.distinct); + assert_eq!( + &SQLSelectItem::UnnamedExpression(ASTNode::SQLIdentifier("name".to_string())), + only(&select.projection) + ); +} + #[test] fn parse_select_wildcard() { let sql = "SELECT * FROM foo";