Skip to content

Commit 04c8f9b

Browse files
committed
SGA-3801 Added support for concatenating string literals saperated by space in mySQL
1 parent b660a3b commit 04c8f9b

File tree

4 files changed

+61
-2
lines changed

4 files changed

+61
-2
lines changed

src/dialect/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,12 @@ pub trait Dialect: Debug + Any {
476476
false
477477
}
478478

479+
// Does the Dialect support concatenating of string literal
480+
// Example: SELECT 'Hello ' "world" => SELECT 'Hello world'
481+
fn supports_concat_quoted_identifiers(&self) -> bool {
482+
false
483+
}
484+
479485
/// Does the dialect support trailing commas in the projection list?
480486
fn supports_projection_trailing_commas(&self) -> bool {
481487
self.supports_trailing_commas()

src/dialect/mysql.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ impl Dialect for MySqlDialect {
7171
true
7272
}
7373

74+
// see <https://dev.mysql.com/doc/refman/8.4/en/string-functions.html#:~:text=mysql%3E%20SELECT%20%27My%27%20%27S%27%20%27QL%27%3B%0A%20%20%20%20%20%20%20%20%2D%3E%20%27MySQL%27>
75+
fn supports_concat_quoted_identifiers(&self) -> bool {
76+
true
77+
}
78+
7479
fn ignores_wildcard_escapes(&self) -> bool {
7580
true
7681
}

src/parser/mod.rs

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9684,8 +9684,18 @@ impl<'a> Parser<'a> {
96849684
// bigdecimal feature is enabled, and is otherwise a no-op
96859685
// (i.e., it returns the input string).
96869686
Token::Number(n, l) => ok_value(Value::Number(Self::parse(n, span.start)?, l)),
9687-
Token::SingleQuotedString(ref s) => ok_value(Value::SingleQuotedString(s.to_string())),
9688-
Token::DoubleQuotedString(ref s) => ok_value(Value::DoubleQuotedString(s.to_string())),
9687+
Token::SingleQuotedString(ref s) => {
9688+
if self.dialect.supports_concat_quoted_identifiers() {
9689+
return ok_value(Value::SingleQuotedString(self.combine_quoted(next_token)));
9690+
}
9691+
ok_value(Value::SingleQuotedString(s.to_string()))
9692+
}
9693+
Token::DoubleQuotedString(ref s) => {
9694+
if self.dialect.supports_concat_quoted_identifiers() {
9695+
return ok_value(Value::DoubleQuotedString(self.combine_quoted(next_token)));
9696+
}
9697+
ok_value(Value::DoubleQuotedString(s.to_string()))
9698+
}
96899699
Token::TripleSingleQuotedString(ref s) => {
96909700
ok_value(Value::TripleSingleQuotedString(s.to_string()))
96919701
}
@@ -9755,6 +9765,35 @@ impl<'a> Parser<'a> {
97559765
}
97569766
}
97579767

9768+
fn is_quoted_string(&self, token: &Token) -> bool {
9769+
matches!(
9770+
token,
9771+
Token::SingleQuotedString(_) | Token::DoubleQuotedString(_)
9772+
)
9773+
}
9774+
9775+
fn get_quoted_string(&self, token: &Token) -> String {
9776+
match token {
9777+
Token::SingleQuotedString(s) => s.clone(),
9778+
Token::DoubleQuotedString(s) => s.clone(),
9779+
_ => String::new(),
9780+
}
9781+
}
9782+
9783+
fn combine_quoted(&mut self, token: TokenWithSpan) -> String {
9784+
let mut combined_string = self.get_quoted_string(&token.token);
9785+
loop {
9786+
let next_token = self.next_token();
9787+
if !self.is_quoted_string(&next_token.token) {
9788+
self.prev_token();
9789+
break;
9790+
}
9791+
let s = self.get_quoted_string(&next_token.token);
9792+
combined_string.push_str(&s);
9793+
}
9794+
combined_string
9795+
}
9796+
97589797
/// Parse an unsigned numeric literal
97599798
pub fn parse_number_value(&mut self) -> Result<ValueWithSpan, ParserError> {
97609799
let value_wrapper = self.parse_value()?;

tests/sqlparser_mysql.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4245,3 +4245,12 @@ fn test_create_index_options() {
42454245
"CREATE INDEX idx_name ON t(c1, c2) USING BTREE LOCK = EXCLUSIVE ALGORITHM = DEFAULT",
42464246
);
42474247
}
4248+
4249+
#[test]
4250+
fn parse_adjacent_string_literal_concatenation() {
4251+
let sql = r#"SELECT 'M' "y" 'S' "q" 'l'"#;
4252+
mysql().one_statement_parses_to(sql, r"SELECT 'MySql'");
4253+
4254+
let sql = "SELECT * FROM t WHERE col = 'Hello' \n ' ' \t 'World!'";
4255+
mysql().one_statement_parses_to(sql, r"SELECT * FROM t WHERE col = 'Hello World!'");
4256+
}

0 commit comments

Comments
 (0)