Skip to content

Commit dc04842

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

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
@@ -490,6 +490,10 @@ impl<'a> Parser<'a> {
490490
if expecting_statement_delimiter && word.keyword == Keyword::END {
491491
break;
492492
}
493+
494+
if expecting_statement_delimiter && word.keyword == Keyword::GO {
495+
expecting_statement_delimiter = false;
496+
}
493497
}
494498
_ => {}
495499
}

tests/sqlparser_mssql.rs

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

2523+
let go_statement_delimiter = "SELECT 1\nGO";
2524+
let stmts = ms().parse_sql_statements(go_statement_delimiter).unwrap();
2525+
assert_eq!(stmts.len(), 2);
2526+
assert_eq!(stmts[1], Statement::Go(GoStatement { count: None }));
2527+
25232528
let bare_go = "GO";
25242529
let stmts = ms().parse_sql_statements(bare_go).unwrap();
25252530
assert_eq!(stmts.len(), 1);
@@ -2553,15 +2558,22 @@ fn parse_mssql_go_keyword() {
25532558
assert_eq!(stmts.len(), 2);
25542559
assert_eq!(stmts[1], Statement::Go(GoStatement { count: None }));
25552560

2556-
let actually_column_alias = "SELECT NULL AS GO";
2557-
let stmt = ms().verified_only_select(actually_column_alias);
2558-
assert_eq!(
2559-
only(stmt.projection),
2560-
SelectItem::ExprWithAlias {
2561-
expr: Expr::Value(Value::Null.with_empty_span()),
2562-
alias: Ident::new("GO"),
2561+
let actually_column_alias = "SELECT NULL GO";
2562+
let stmts = ms().parse_sql_statements(actually_column_alias).unwrap();
2563+
assert_eq!(stmts.len(), 1);
2564+
match &stmts[0] {
2565+
Statement::Query(query) => {
2566+
let select = query.body.as_select().unwrap();
2567+
assert_eq!(
2568+
only(select.clone().projection),
2569+
SelectItem::ExprWithAlias {
2570+
expr: Expr::Value(Value::Null.with_empty_span()),
2571+
alias: Ident::new("GO"),
2572+
}
2573+
);
25632574
}
2564-
);
2575+
_ => panic!("Expected Query statement"),
2576+
}
25652577

25662578
let invalid_go_position = "SELECT 1; GO";
25672579
let err = ms().parse_sql_statements(invalid_go_position);
@@ -2574,7 +2586,7 @@ fn parse_mssql_go_keyword() {
25742586
let err = ms().parse_sql_statements(invalid_go_count);
25752587
assert_eq!(
25762588
err.unwrap_err().to_string(),
2577-
"sql parser error: Expected: end of statement, found: x"
2589+
"sql parser error: Expected: literal int or newline, found: x"
25782590
);
25792591
}
25802592

0 commit comments

Comments
 (0)