Skip to content

Commit af1ac86

Browse files
authored
Add TrimWhereField for parse_trim_expr (apache#334)
* Remove Box from `trim_where` * Add TrimWhereField for `parse_trim_expr` * Add negative test case
1 parent 5ce6717 commit af1ac86

File tree

4 files changed

+41
-5
lines changed

4 files changed

+41
-5
lines changed

src/ast/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ pub use self::query::{
4040
Query, Select, SelectItem, SetExpr, SetOperator, TableAlias, TableFactor, TableWithJoins, Top,
4141
Values, With,
4242
};
43-
pub use self::value::{DateTimeField, Value};
43+
pub use self::value::{DateTimeField, TrimWhereField, Value};
4444

4545
struct DisplaySeparated<'a, T>
4646
where
@@ -231,7 +231,7 @@ pub enum Expr {
231231
Trim {
232232
expr: Box<Expr>,
233233
// ([BOTH | LEADING | TRAILING], <expr>)
234-
trim_where: Option<(Box<Ident>, Box<Expr>)>,
234+
trim_where: Option<(TrimWhereField, Box<Expr>)>,
235235
},
236236
/// `expr COLLATE collation`
237237
Collate {

src/ast/value.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,22 @@ impl<'a> fmt::Display for EscapeSingleQuoteString<'a> {
157157
pub fn escape_single_quote_string(s: &str) -> EscapeSingleQuoteString<'_> {
158158
EscapeSingleQuoteString(s)
159159
}
160+
161+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
162+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
163+
pub enum TrimWhereField {
164+
Both,
165+
Leading,
166+
Trailing,
167+
}
168+
169+
impl fmt::Display for TrimWhereField {
170+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171+
use TrimWhereField::*;
172+
f.write_str(match self {
173+
Both => "BOTH",
174+
Leading => "LEADING",
175+
Trailing => "TRAILING",
176+
})
177+
}
178+
}

src/parser.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -666,21 +666,33 @@ impl<'a> Parser<'a> {
666666
.iter()
667667
.any(|d| word.keyword == *d)
668668
{
669-
let ident = self.parse_identifier()?;
669+
let trim_where = self.parse_trim_where()?;
670670
let sub_expr = self.parse_expr()?;
671671
self.expect_keyword(Keyword::FROM)?;
672-
where_expr = Some((ident, sub_expr))
672+
where_expr = Some((trim_where, Box::new(sub_expr)));
673673
}
674674
}
675675
let expr = self.parse_expr()?;
676676
self.expect_token(&Token::RParen)?;
677677

678678
Ok(Expr::Trim {
679679
expr: Box::new(expr),
680-
trim_where: where_expr.map(|(ident, expr)| (Box::new(ident), Box::new(expr))),
680+
trim_where: where_expr,
681681
})
682682
}
683683

684+
pub fn parse_trim_where(&mut self) -> Result<TrimWhereField, ParserError> {
685+
match self.next_token() {
686+
Token::Word(w) => match w.keyword {
687+
Keyword::BOTH => Ok(TrimWhereField::Both),
688+
Keyword::LEADING => Ok(TrimWhereField::Leading),
689+
Keyword::TRAILING => Ok(TrimWhereField::Trailing),
690+
_ => self.expected("trim_where field", Token::Word(w))?,
691+
},
692+
unexpected => self.expected("trim_where field", unexpected),
693+
}
694+
}
695+
684696
/// Parse a SQL LISTAGG expression, e.g. `LISTAGG(...) WITHIN GROUP (ORDER BY ...)`.
685697
pub fn parse_listagg_expr(&mut self) -> Result<Expr, ParserError> {
686698
self.expect_token(&Token::LParen)?;

tests/sqlparser_common.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2765,6 +2765,11 @@ fn parse_trim() {
27652765
);
27662766

27672767
one_statement_parses_to("SELECT TRIM(' foo ')", "SELECT TRIM(' foo ')");
2768+
2769+
assert_eq!(
2770+
ParserError::ParserError("Expected ), found: 'xyz'".to_owned()),
2771+
parse_sql_statements("SELECT TRIM(FOO 'xyz' FROM 'xyzfooxyz')").unwrap_err()
2772+
);
27682773
}
27692774

27702775
#[test]

0 commit comments

Comments
 (0)