Skip to content

Commit c417dfd

Browse files
committed
Fix not treating GO as a statement delimiter next to a query
1 parent b0869d1 commit c417dfd

File tree

3 files changed

+49
-11
lines changed

3 files changed

+49
-11
lines changed

src/dialect/mssql.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use crate::ast::{
2323
use crate::dialect::Dialect;
2424
use crate::keywords::{self, Keyword};
2525
use crate::parser::{Parser, ParserError};
26-
use crate::tokenizer::Token;
26+
use crate::tokenizer::{Token, Whitespace};
2727
#[cfg(not(feature = "std"))]
2828
use alloc::{vec, vec::Vec};
2929

@@ -128,7 +128,29 @@ impl Dialect for MsSqlDialect {
128128
&[GranteesType::Public]
129129
}
130130

131-
fn is_column_alias(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
131+
fn is_column_alias(&self, kw: &Keyword, parser: &mut Parser) -> bool {
132+
// if:
133+
// - keyword is `GO`, and
134+
// - looking backwards there's only (any) whitespace preceded by a newline
135+
// then: `GO` iSN'T a column alias
136+
if kw == &Keyword::GO {
137+
let mut look_back_count = 2;
138+
loop {
139+
let prev_index = parser.index().saturating_sub(look_back_count);
140+
if prev_index == 0 {
141+
break;
142+
}
143+
let prev_token = parser.token_at(prev_index);
144+
match prev_token.token {
145+
Token::Whitespace(ref w) => match w {
146+
Whitespace::Newline => return false,
147+
_ => look_back_count += 1,
148+
},
149+
_ => break,
150+
};
151+
}
152+
}
153+
132154
!keywords::RESERVED_FOR_COLUMN_ALIAS.contains(kw) && !RESERVED_FOR_COLUMN_ALIAS.contains(kw)
133155
}
134156

src/parser/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,10 @@ impl<'a> Parser<'a> {
495495
if expecting_statement_delimiter && word.keyword == Keyword::END {
496496
break;
497497
}
498+
499+
if expecting_statement_delimiter && word.keyword == Keyword::GO {
500+
expecting_statement_delimiter = false;
501+
}
498502
}
499503
_ => {}
500504
}

tests/sqlparser_mssql.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2536,6 +2536,11 @@ fn parse_mssql_go_keyword() {
25362536
assert_eq!(stmts.len(), 2);
25372537
assert_eq!(stmts[1], Statement::Go(GoStatement { count: Some(5) }));
25382538

2539+
let go_statement_delimiter = "SELECT 1\nGO";
2540+
let stmts = ms().parse_sql_statements(go_statement_delimiter).unwrap();
2541+
assert_eq!(stmts.len(), 2);
2542+
assert_eq!(stmts[1], Statement::Go(GoStatement { count: None }));
2543+
25392544
let bare_go = "GO";
25402545
let stmts = ms().parse_sql_statements(bare_go).unwrap();
25412546
assert_eq!(stmts.len(), 1);
@@ -2569,15 +2574,22 @@ fn parse_mssql_go_keyword() {
25692574
assert_eq!(stmts.len(), 2);
25702575
assert_eq!(stmts[1], Statement::Go(GoStatement { count: None }));
25712576

2572-
let actually_column_alias = "SELECT NULL AS GO";
2573-
let stmt = ms().verified_only_select(actually_column_alias);
2574-
assert_eq!(
2575-
only(stmt.projection),
2576-
SelectItem::ExprWithAlias {
2577-
expr: Expr::Value(Value::Null.with_empty_span()),
2578-
alias: Ident::new("GO"),
2577+
let actually_column_alias = "SELECT NULL GO";
2578+
let stmts = ms().parse_sql_statements(actually_column_alias).unwrap();
2579+
assert_eq!(stmts.len(), 1);
2580+
match &stmts[0] {
2581+
Statement::Query(query) => {
2582+
let select = query.body.as_select().unwrap();
2583+
assert_eq!(
2584+
only(select.clone().projection),
2585+
SelectItem::ExprWithAlias {
2586+
expr: Expr::Value(Value::Null.with_empty_span()),
2587+
alias: Ident::new("GO"),
2588+
}
2589+
);
25792590
}
2580-
);
2591+
_ => panic!("Expected Query statement"),
2592+
}
25812593

25822594
let invalid_go_position = "SELECT 1; GO";
25832595
let err = ms().parse_sql_statements(invalid_go_position);
@@ -2590,7 +2602,7 @@ fn parse_mssql_go_keyword() {
25902602
let err = ms().parse_sql_statements(invalid_go_count);
25912603
assert_eq!(
25922604
err.unwrap_err().to_string(),
2593-
"sql parser error: Expected: end of statement, found: x"
2605+
"sql parser error: Expected: literal int or newline, found: x"
25942606
);
25952607
}
25962608

0 commit comments

Comments
 (0)