Skip to content

Commit 443f492

Browse files
authored
Require space after -- to start single line comment in MySQL (#1705)
1 parent 751dc5a commit 443f492

File tree

4 files changed

+127
-6
lines changed

4 files changed

+127
-6
lines changed

src/dialect/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,15 @@ pub trait Dialect: Debug + Any {
881881
fn supports_table_hints(&self) -> bool {
882882
false
883883
}
884+
885+
/// Returns true if this dialect requires a whitespace character after `--` to start a single line comment.
886+
///
887+
/// MySQL: <https://dev.mysql.com/doc/refman/8.4/en/ansi-diff-comments.html>
888+
/// e.g. UPDATE account SET balance=balance--1
889+
// WHERE account_id=5752 ^^^ will be interpreted as two minus signs instead of a comment
890+
fn requires_single_line_comment_whitespace(&self) -> bool {
891+
false
892+
}
884893
}
885894

886895
/// This represents the operators for which precedence must be defined

src/dialect/mysql.rs

+4
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ impl Dialect for MySqlDialect {
125125
fn supports_table_hints(&self) -> bool {
126126
true
127127
}
128+
129+
fn requires_single_line_comment_whitespace(&self) -> bool {
130+
true
131+
}
128132
}
129133

130134
/// `LOCK TABLES`

src/tokenizer.rs

+99-6
Original file line numberDiff line numberDiff line change
@@ -1229,14 +1229,26 @@ impl<'a> Tokenizer<'a> {
12291229
// operators
12301230
'-' => {
12311231
chars.next(); // consume the '-'
1232+
12321233
match chars.peek() {
12331234
Some('-') => {
1234-
chars.next(); // consume the second '-', starting a single-line comment
1235-
let comment = self.tokenize_single_line_comment(chars);
1236-
Ok(Some(Token::Whitespace(Whitespace::SingleLineComment {
1237-
prefix: "--".to_owned(),
1238-
comment,
1239-
})))
1235+
let mut is_comment = true;
1236+
if self.dialect.requires_single_line_comment_whitespace() {
1237+
is_comment = Some(' ') == chars.peekable.clone().nth(1);
1238+
}
1239+
1240+
if is_comment {
1241+
chars.next(); // consume second '-'
1242+
let comment = self.tokenize_single_line_comment(chars);
1243+
return Ok(Some(Token::Whitespace(
1244+
Whitespace::SingleLineComment {
1245+
prefix: "--".to_owned(),
1246+
comment,
1247+
},
1248+
)));
1249+
}
1250+
1251+
self.start_binop(chars, "-", Token::Minus)
12401252
}
12411253
Some('>') => {
12421254
chars.next();
@@ -3685,4 +3697,85 @@ mod tests {
36853697
],
36863698
);
36873699
}
3700+
3701+
#[test]
3702+
fn test_whitespace_required_after_single_line_comment() {
3703+
all_dialects_where(|dialect| dialect.requires_single_line_comment_whitespace())
3704+
.tokenizes_to(
3705+
"SELECT --'abc'",
3706+
vec![
3707+
Token::make_keyword("SELECT"),
3708+
Token::Whitespace(Whitespace::Space),
3709+
Token::Minus,
3710+
Token::Minus,
3711+
Token::SingleQuotedString("abc".to_string()),
3712+
],
3713+
);
3714+
3715+
all_dialects_where(|dialect| dialect.requires_single_line_comment_whitespace())
3716+
.tokenizes_to(
3717+
"SELECT -- 'abc'",
3718+
vec![
3719+
Token::make_keyword("SELECT"),
3720+
Token::Whitespace(Whitespace::Space),
3721+
Token::Whitespace(Whitespace::SingleLineComment {
3722+
prefix: "--".to_string(),
3723+
comment: " 'abc'".to_string(),
3724+
}),
3725+
],
3726+
);
3727+
3728+
all_dialects_where(|dialect| dialect.requires_single_line_comment_whitespace())
3729+
.tokenizes_to(
3730+
"SELECT --",
3731+
vec![
3732+
Token::make_keyword("SELECT"),
3733+
Token::Whitespace(Whitespace::Space),
3734+
Token::Minus,
3735+
Token::Minus,
3736+
],
3737+
);
3738+
}
3739+
3740+
#[test]
3741+
fn test_whitespace_not_required_after_single_line_comment() {
3742+
all_dialects_where(|dialect| !dialect.requires_single_line_comment_whitespace())
3743+
.tokenizes_to(
3744+
"SELECT --'abc'",
3745+
vec![
3746+
Token::make_keyword("SELECT"),
3747+
Token::Whitespace(Whitespace::Space),
3748+
Token::Whitespace(Whitespace::SingleLineComment {
3749+
prefix: "--".to_string(),
3750+
comment: "'abc'".to_string(),
3751+
}),
3752+
],
3753+
);
3754+
3755+
all_dialects_where(|dialect| !dialect.requires_single_line_comment_whitespace())
3756+
.tokenizes_to(
3757+
"SELECT -- 'abc'",
3758+
vec![
3759+
Token::make_keyword("SELECT"),
3760+
Token::Whitespace(Whitespace::Space),
3761+
Token::Whitespace(Whitespace::SingleLineComment {
3762+
prefix: "--".to_string(),
3763+
comment: " 'abc'".to_string(),
3764+
}),
3765+
],
3766+
);
3767+
3768+
all_dialects_where(|dialect| !dialect.requires_single_line_comment_whitespace())
3769+
.tokenizes_to(
3770+
"SELECT --",
3771+
vec![
3772+
Token::make_keyword("SELECT"),
3773+
Token::Whitespace(Whitespace::Space),
3774+
Token::Whitespace(Whitespace::SingleLineComment {
3775+
prefix: "--".to_string(),
3776+
comment: "".to_string(),
3777+
}),
3778+
],
3779+
);
3780+
}
36883781
}

tests/sqlparser_mysql.rs

+15
Original file line numberDiff line numberDiff line change
@@ -3250,3 +3250,18 @@ fn parse_double_precision() {
32503250
"CREATE TABLE foo (bar DOUBLE(11,0))",
32513251
);
32523252
}
3253+
3254+
#[test]
3255+
fn parse_looks_like_single_line_comment() {
3256+
mysql().one_statement_parses_to(
3257+
"UPDATE account SET balance=balance--1 WHERE account_id=5752",
3258+
"UPDATE account SET balance = balance - -1 WHERE account_id = 5752",
3259+
);
3260+
mysql().one_statement_parses_to(
3261+
r#"
3262+
UPDATE account SET balance=balance-- 1
3263+
WHERE account_id=5752
3264+
"#,
3265+
"UPDATE account SET balance = balance WHERE account_id = 5752",
3266+
);
3267+
}

0 commit comments

Comments
 (0)