Skip to content

Commit bfd2ff2

Browse files
authored
fix: error recovery for extra comma with distinct (#25)
1 parent f728f57 commit bfd2ff2

File tree

3 files changed

+52
-1
lines changed

3 files changed

+52
-1
lines changed

crates/postgresql-cst-parser/src/cst/lr_parse_state.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,8 @@ impl<'a> LRParseState<'a> {
4747
pub fn last_syntax_kind(&self) -> Option<SyntaxKind> {
4848
self.stack.last().map(|(_, node)| node.into())
4949
}
50+
51+
pub fn iter_syntax_kind_rev(&'a self) -> impl Iterator<Item = SyntaxKind> + 'a {
52+
self.stack.iter().rev().map(|(_, node)| node.into())
53+
}
5054
}

crates/postgresql-cst-parser/src/lib.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,30 @@ mod tests {
6767
let s = r#"select /*param*/ as A
6868
from /*#foo*/
6969
;
70+
"#;
71+
assert!(parse_2way(s).is_ok());
72+
}
73+
74+
#[test]
75+
fn test_2way_error_recovery_distinct_on() {
76+
let s = r#"select distinct on (col1) , t.* from tbl t;
77+
;
78+
"#;
79+
assert!(parse_2way(s).is_ok());
80+
}
81+
82+
#[test]
83+
fn test_2way_error_recovery_distinct() {
84+
let s = r#"select distinct , t.* from tbl t;
85+
;
86+
"#;
87+
assert!(parse_2way(s).is_ok());
88+
}
89+
90+
#[test]
91+
fn test_2way_error_recovery_all() {
92+
let s = r#"select all , t.* from tbl t;
93+
;
7094
"#;
7195
assert!(parse_2way(s).is_ok());
7296
}

crates/postgresql-cst-parser/src/transform/skip_extra_comma.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,30 @@ pub struct SkipExtraComma;
88
impl SkipExtraComma {
99
fn allow_extra_comma<'a>(lr_parse_state: &LRParseState<'a>) -> bool {
1010
match lr_parse_state.last_syntax_kind() {
11-
Some(SyntaxKind::FROM) | Some(SyntaxKind::BY) | Some(SyntaxKind::SELECT) => true,
11+
Some(SyntaxKind::FROM)
12+
| Some(SyntaxKind::BY)
13+
| Some(SyntaxKind::SELECT)
14+
| Some(SyntaxKind::ALL)
15+
| Some(SyntaxKind::DISTINCT) => true,
16+
17+
Some(SyntaxKind::RParen) => {
18+
// select distinct on
19+
let expected_select_distinct_on_kinds = [
20+
SyntaxKind::RParen,
21+
SyntaxKind::expr_list,
22+
SyntaxKind::LParen,
23+
SyntaxKind::ON,
24+
SyntaxKind::DISTINCT,
25+
SyntaxKind::SELECT,
26+
];
27+
28+
let actual_kinds: Vec<_> = lr_parse_state
29+
.iter_syntax_kind_rev()
30+
.take(expected_select_distinct_on_kinds.len())
31+
.collect();
32+
33+
expected_select_distinct_on_kinds.as_ref() == actual_kinds.as_slice()
34+
}
1235
_ => false,
1336
}
1437
}

0 commit comments

Comments
 (0)