Skip to content

Commit 04419bb

Browse files
mvzinkayman-sigma
authored andcommitted
Parse SUBSTR as alias for SUBSTRING (apache#1769)
1 parent de5542f commit 04419bb

File tree

7 files changed

+32
-4
lines changed

7 files changed

+32
-4
lines changed

src/ast/mod.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,10 @@ pub enum Expr {
897897
/// true if the expression is represented using the `SUBSTRING(expr, start, len)` syntax
898898
/// This flag is used for formatting.
899899
special: bool,
900+
901+
/// true if the expression is represented using the `SUBSTR` shorthand
902+
/// This flag is used for formatting.
903+
shorthand: bool,
900904
},
901905
/// ```sql
902906
/// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
@@ -1737,8 +1741,13 @@ impl fmt::Display for Expr {
17371741
substring_from,
17381742
substring_for,
17391743
special,
1744+
shorthand,
17401745
} => {
1741-
write!(f, "SUBSTRING({expr}")?;
1746+
f.write_str("SUBSTR")?;
1747+
if !*shorthand {
1748+
f.write_str("ING")?;
1749+
}
1750+
write!(f, "({expr}")?;
17421751
if let Some(from_part) = substring_from {
17431752
if *special {
17441753
write!(f, ", {from_part}")?;

src/ast/spans.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1508,6 +1508,7 @@ impl Spanned for Expr {
15081508
substring_from,
15091509
substring_for,
15101510
special: _,
1511+
shorthand: _,
15111512
} => union_spans(
15121513
core::iter::once(expr.span())
15131514
.chain(substring_from.as_ref().map(|i| i.span()))

src/keywords.rs

+1
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,7 @@ define_keywords!(
841841
STRING,
842842
STRUCT,
843843
SUBMULTISET,
844+
SUBSTR,
844845
SUBSTRING,
845846
SUBSTRING_REGEX,
846847
SUCCEEDS,

src/parser/mod.rs

+15-3
Original file line numberDiff line numberDiff line change
@@ -1302,7 +1302,10 @@ impl<'a> Parser<'a> {
13021302
Keyword::POSITION if self.peek_token_ref().token == Token::LParen => {
13031303
Ok(Some(self.parse_position_expr(w.clone().into_ident(w_span))?))
13041304
}
1305-
Keyword::SUBSTRING => Ok(Some(self.parse_substring_expr()?)),
1305+
Keyword::SUBSTR | Keyword::SUBSTRING => {
1306+
self.prev_token();
1307+
Ok(Some(self.parse_substring()?))
1308+
}
13061309
Keyword::OVERLAY => Ok(Some(self.parse_overlay_expr()?)),
13071310
Keyword::TRIM => Ok(Some(self.parse_trim_expr()?)),
13081311
Keyword::INTERVAL => Ok(Some(self.parse_interval()?)),
@@ -2412,8 +2415,16 @@ impl<'a> Parser<'a> {
24122415
}
24132416
}
24142417

2415-
pub fn parse_substring_expr(&mut self) -> Result<Expr, ParserError> {
2416-
// PARSE SUBSTRING (EXPR [FROM 1] [FOR 3])
2418+
// { SUBSTRING | SUBSTR } (<EXPR> [FROM 1] [FOR 3])
2419+
pub fn parse_substring(&mut self) -> Result<Expr, ParserError> {
2420+
let shorthand = match self.expect_one_of_keywords(&[Keyword::SUBSTR, Keyword::SUBSTRING])? {
2421+
Keyword::SUBSTR => true,
2422+
Keyword::SUBSTRING => false,
2423+
_ => {
2424+
self.prev_token();
2425+
return self.expected("SUBSTR or SUBSTRING", self.peek_token());
2426+
}
2427+
};
24172428
self.expect_token(&Token::LParen)?;
24182429
let expr = self.parse_expr()?;
24192430
let mut from_expr = None;
@@ -2433,6 +2444,7 @@ impl<'a> Parser<'a> {
24332444
substring_from: from_expr.map(Box::new),
24342445
substring_for: to_expr.map(Box::new),
24352446
special,
2447+
shorthand,
24362448
})
24372449
}
24382450

tests/sqlparser_common.rs

+3
Original file line numberDiff line numberDiff line change
@@ -7608,6 +7608,9 @@ fn parse_substring() {
76087608
verified_stmt("SELECT SUBSTRING('1', 1, 3)");
76097609
verified_stmt("SELECT SUBSTRING('1', 1)");
76107610
verified_stmt("SELECT SUBSTRING('1' FOR 3)");
7611+
verified_stmt("SELECT SUBSTRING('foo' FROM 1 FOR 2) FROM t");
7612+
verified_stmt("SELECT SUBSTR('foo' FROM 1 FOR 2) FROM t");
7613+
verified_stmt("SELECT SUBSTR('foo', 1, 2) FROM t");
76117614
}
76127615

76137616
#[test]

tests/sqlparser_mssql.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1133,6 +1133,7 @@ fn parse_substring_in_select() {
11331133
(number("1")).with_empty_span()
11341134
))),
11351135
special: true,
1136+
shorthand: false,
11361137
})],
11371138
into: None,
11381139
from: vec![TableWithJoins {

tests/sqlparser_mysql.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2590,6 +2590,7 @@ fn parse_substring_in_select() {
25902590
(number("1")).with_empty_span()
25912591
))),
25922592
special: true,
2593+
shorthand: false,
25932594
})],
25942595
into: None,
25952596
from: vec![TableWithJoins {

0 commit comments

Comments
 (0)