Skip to content

Commit 5ed5af1

Browse files
committed
Add Distinct::All variant to preserve SELECT ALL in AST
Previously, `SELECT ALL` was parsed but the ALL keyword was discarded, with `one_statement_parses_to` tests verifying it normalized away. Now the parser returns `Distinct::All` so the AST represents the original SQL. Also improves error messages for conflicting ALL/DISTINCT to indicate which keyword came first.
1 parent 3ac5670 commit 5ed5af1

3 files changed

Lines changed: 43 additions & 15 deletions

File tree

src/ast/query.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3351,8 +3351,14 @@ impl fmt::Display for NonBlock {
33513351
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
33523352
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
33533353
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3354-
/// `DISTINCT` or `DISTINCT ON (...)` modifiers for `SELECT` lists.
3354+
/// `ALL`, `DISTINCT`, or `DISTINCT ON (...)` modifiers for `SELECT` lists.
33553355
pub enum Distinct {
3356+
/// `ALL` (keep duplicate rows)
3357+
///
3358+
/// Generally this is the default if omitted, but omission should be represented as
3359+
/// `None::<Option<Distinct>>`
3360+
All,
3361+
33563362
/// `DISTINCT` (remove duplicate rows)
33573363
Distinct,
33583364

@@ -3363,6 +3369,7 @@ pub enum Distinct {
33633369
impl fmt::Display for Distinct {
33643370
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
33653371
match self {
3372+
Distinct::All => write!(f, "ALL"),
33663373
Distinct::Distinct => write!(f, "DISTINCT"),
33673374
Distinct::On(col_names) => {
33683375
let col_names = display_comma_separated(col_names);

src/parser/mod.rs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4927,16 +4927,27 @@ impl<'a> Parser<'a> {
49274927
/// and results in a [`ParserError`] if both `ALL` and `DISTINCT` are found.
49284928
pub fn parse_all_or_distinct(&mut self) -> Result<Option<Distinct>, ParserError> {
49294929
let loc = self.peek_token().span.start;
4930-
let all = self.parse_keyword(Keyword::ALL);
4931-
let distinct = self.parse_keyword(Keyword::DISTINCT);
4932-
if !distinct {
4933-
return Ok(None);
4934-
}
4935-
if all {
4936-
return parser_err!("Cannot specify both ALL and DISTINCT".to_string(), loc);
4937-
}
4938-
let on = self.parse_keyword(Keyword::ON);
4939-
if !on {
4930+
let distinct = match self.parse_one_of_keywords(&[Keyword::ALL, Keyword::DISTINCT]) {
4931+
Some(Keyword::ALL) => {
4932+
if self.peek_keyword(Keyword::DISTINCT) {
4933+
return parser_err!("Cannot specify ALL then DISTINCT".to_string(), loc);
4934+
}
4935+
Some(Distinct::All)
4936+
}
4937+
Some(Keyword::DISTINCT) => {
4938+
if self.peek_keyword(Keyword::ALL) {
4939+
return parser_err!("Cannot specify DISTINCT then ALL".to_string(), loc);
4940+
}
4941+
Some(Distinct::Distinct)
4942+
}
4943+
None => return Ok(None),
4944+
_ => return parser_err!("ALL or DISTINCT", loc),
4945+
};
4946+
4947+
let Some(Distinct::Distinct) = distinct else {
4948+
return Ok(distinct);
4949+
};
4950+
if !self.parse_keyword(Keyword::ON) {
49404951
return Ok(Some(Distinct::Distinct));
49414952
}
49424953

tests/sqlparser_common.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,14 +1074,24 @@ fn parse_select_distinct_missing_paren() {
10741074

10751075
#[test]
10761076
fn parse_select_all() {
1077-
one_statement_parses_to("SELECT ALL name FROM customer", "SELECT name FROM customer");
1077+
verified_stmt("SELECT ALL name FROM customer");
10781078
}
10791079

10801080
#[test]
10811081
fn parse_select_all_distinct() {
10821082
let result = parse_sql_statements("SELECT ALL DISTINCT name FROM customer");
10831083
assert_eq!(
1084-
ParserError::ParserError("Cannot specify both ALL and DISTINCT".to_string()),
1084+
ParserError::ParserError("Cannot specify ALL then DISTINCT".to_string()),
1085+
result.unwrap_err(),
1086+
);
1087+
let result = parse_sql_statements("SELECT DISTINCT ALL name FROM customer");
1088+
assert_eq!(
1089+
ParserError::ParserError("Cannot specify DISTINCT then ALL".to_string()),
1090+
result.unwrap_err(),
1091+
);
1092+
let result = parse_sql_statements("SELECT ALL DISTINCT ON(name) name FROM customer");
1093+
assert_eq!(
1094+
ParserError::ParserError("Cannot specify ALL then DISTINCT".to_string()),
10851095
result.unwrap_err(),
10861096
);
10871097
}
@@ -14830,9 +14840,9 @@ fn test_load_extension() {
1483014840
#[test]
1483114841
fn test_select_top() {
1483214842
let dialects = all_dialects_where(|d| d.supports_top_before_distinct());
14833-
dialects.one_statement_parses_to("SELECT ALL * FROM tbl", "SELECT * FROM tbl");
14843+
dialects.verified_stmt("SELECT ALL * FROM tbl");
1483414844
dialects.verified_stmt("SELECT TOP 3 * FROM tbl");
14835-
dialects.one_statement_parses_to("SELECT TOP 3 ALL * FROM tbl", "SELECT TOP 3 * FROM tbl");
14845+
dialects.verified_stmt("SELECT TOP 3 ALL * FROM tbl");
1483614846
dialects.verified_stmt("SELECT TOP 3 DISTINCT * FROM tbl");
1483714847
dialects.verified_stmt("SELECT TOP 3 DISTINCT a, b, c FROM tbl");
1483814848
}

0 commit comments

Comments
 (0)