Skip to content

Commit 2d1a987

Browse files
committed
Extract common logic to look back for a newline to a helper
1 parent e61b569 commit 2d1a987

3 files changed

Lines changed: 50 additions & 31 deletions

File tree

src/dialect/mssql.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,16 @@ impl Dialect for MsSqlDialect {
128128
}
129129

130130
fn is_select_item_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
131+
// if we find maybe whitespace then a newline looking backward, then `GO` ISN'T a column alias
132+
// if we can't find a newline then we assume that `GO` IS a column alias
133+
if kw == &Keyword::GO
134+
&& parser
135+
.expect_previously_only_whitespace_until_newline()
136+
.is_ok()
137+
{
138+
return false;
139+
}
140+
131141
match kw {
132142
// List of keywords that cannot be used as select item (column) aliases in MSSQL
133143
// regardless of whether the alias is explicit or implicit.

src/parser/mod.rs

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4579,6 +4579,44 @@ impl<'a> Parser<'a> {
45794579
)
45804580
}
45814581

4582+
/// Look backwards in the token stream and expect that there was only whitespace tokens until the previous newline
4583+
pub fn expect_previously_only_whitespace_until_newline(&mut self) -> Result<(), ParserError> {
4584+
let mut look_back_count = 2;
4585+
loop {
4586+
let prev_index = self.index.saturating_sub(look_back_count);
4587+
if prev_index == 0 {
4588+
break;
4589+
}
4590+
let prev_token = self.token_at(prev_index);
4591+
match prev_token.token {
4592+
Token::Whitespace(ref w) => match w {
4593+
Whitespace::Newline => break,
4594+
// special consideration required for single line comments since that string includes the newline
4595+
Whitespace::SingleLineComment { comment, prefix: _ } => {
4596+
if comment.ends_with('\n') {
4597+
break;
4598+
}
4599+
look_back_count += 1;
4600+
}
4601+
_ => look_back_count += 1,
4602+
},
4603+
_ => {
4604+
let current_token = self.get_current_token();
4605+
if prev_token == current_token {
4606+
// if we are at the start of the statement, we can skip this check
4607+
break;
4608+
}
4609+
4610+
self.expected(
4611+
&format!("newline before current token ({})", current_token),
4612+
prev_token.clone(),
4613+
)?
4614+
}
4615+
};
4616+
}
4617+
Ok(())
4618+
}
4619+
45824620
/// If the current token is the `expected` keyword, consume it and returns
45834621
/// true. Otherwise, no tokens are consumed and returns false.
45844622
#[must_use]
@@ -19654,36 +19692,7 @@ impl<'a> Parser<'a> {
1965419692

1965519693
/// Parse [Statement::Go]
1965619694
fn parse_go(&mut self) -> Result<Statement, ParserError> {
19657-
// previous token should be a newline (skipping non-newline whitespace)
19658-
// see also, `previous_token`
19659-
let mut look_back_count = 2;
19660-
loop {
19661-
let prev_index = self.index.saturating_sub(look_back_count);
19662-
if prev_index == 0 {
19663-
break;
19664-
}
19665-
let prev_token = self.token_at(prev_index);
19666-
match prev_token.token {
19667-
Token::Whitespace(ref w) => match w {
19668-
Whitespace::Newline => break,
19669-
Whitespace::SingleLineComment { comment, prefix: _ } => {
19670-
if comment.ends_with('\n') {
19671-
break;
19672-
}
19673-
look_back_count += 1;
19674-
}
19675-
_ => look_back_count += 1,
19676-
},
19677-
_ => {
19678-
if prev_token == self.get_current_token() {
19679-
// if we are at the start of the statement, we can skip this check
19680-
break;
19681-
}
19682-
19683-
self.expected("newline before GO", prev_token.clone())?
19684-
}
19685-
};
19686-
}
19695+
self.expect_previously_only_whitespace_until_newline()?;
1968719696

1968819697
let count = loop {
1968919698
// using this peek function because we want to halt this statement parsing upon newline

tests/sqlparser_mssql.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2966,7 +2966,7 @@ fn parse_mssql_go_keyword() {
29662966
let err = ms().parse_sql_statements(invalid_go_position);
29672967
assert_eq!(
29682968
err.unwrap_err().to_string(),
2969-
"sql parser error: Expected: newline before GO, found: ;"
2969+
"sql parser error: Expected: newline before current token (GO), found: ;"
29702970
);
29712971

29722972
let invalid_go_count = "SELECT 1\nGO x";

0 commit comments

Comments
 (0)