mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-18 21:20:15 +00:00
Support for SIMILAR TO
syntax, change Like
and ILike
to Expr
variants, allow escape char for like/ilike (#569)
* Remove [not]like,[not]ilike from binary operator list * Add like, ilike and similar as an expr variant. Also adds support for escape char to like/ilike * Add parsing logic for similar to, update parsing logic for like/ilike * Add tests for similar to, update tests for like/ilike * Fix linter warnings * remove additional copyright license from files * Add more coverage w/wo escape char for like,ilike,similar to
This commit is contained in:
parent
18881f8fcf
commit
f07063f0cd
4 changed files with 237 additions and 57 deletions
|
@ -1178,17 +1178,6 @@ impl<'a> Parser<'a> {
|
|||
Token::Word(w) => match w.keyword {
|
||||
Keyword::AND => Some(BinaryOperator::And),
|
||||
Keyword::OR => Some(BinaryOperator::Or),
|
||||
Keyword::LIKE => Some(BinaryOperator::Like),
|
||||
Keyword::ILIKE => Some(BinaryOperator::ILike),
|
||||
Keyword::NOT => {
|
||||
if self.parse_keyword(Keyword::LIKE) {
|
||||
Some(BinaryOperator::NotLike)
|
||||
} else if self.parse_keyword(Keyword::ILIKE) {
|
||||
Some(BinaryOperator::NotILike)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Keyword::XOR => Some(BinaryOperator::Xor),
|
||||
Keyword::OPERATOR if dialect_of!(self is PostgreSqlDialect | GenericDialect) => {
|
||||
self.expect_token(&Token::LParen)?;
|
||||
|
@ -1282,13 +1271,39 @@ impl<'a> Parser<'a> {
|
|||
self.expected("Expected Token::Word after AT", tok)
|
||||
}
|
||||
}
|
||||
Keyword::NOT | Keyword::IN | Keyword::BETWEEN => {
|
||||
Keyword::NOT
|
||||
| Keyword::IN
|
||||
| Keyword::BETWEEN
|
||||
| Keyword::LIKE
|
||||
| Keyword::ILIKE
|
||||
| Keyword::SIMILAR => {
|
||||
self.prev_token();
|
||||
let negated = self.parse_keyword(Keyword::NOT);
|
||||
if self.parse_keyword(Keyword::IN) {
|
||||
self.parse_in(expr, negated)
|
||||
} else if self.parse_keyword(Keyword::BETWEEN) {
|
||||
self.parse_between(expr, negated)
|
||||
} else if self.parse_keyword(Keyword::LIKE) {
|
||||
Ok(Expr::Like {
|
||||
negated,
|
||||
expr: Box::new(expr),
|
||||
pattern: Box::new(self.parse_value()?),
|
||||
escape_char: self.parse_escape_char()?,
|
||||
})
|
||||
} else if self.parse_keyword(Keyword::ILIKE) {
|
||||
Ok(Expr::ILike {
|
||||
negated,
|
||||
expr: Box::new(expr),
|
||||
pattern: Box::new(self.parse_value()?),
|
||||
escape_char: self.parse_escape_char()?,
|
||||
})
|
||||
} else if self.parse_keywords(&[Keyword::SIMILAR, Keyword::TO]) {
|
||||
Ok(Expr::SimilarTo {
|
||||
negated,
|
||||
expr: Box::new(expr),
|
||||
pattern: Box::new(self.parse_value()?),
|
||||
escape_char: self.parse_escape_char()?,
|
||||
})
|
||||
} else {
|
||||
self.expected("IN or BETWEEN after NOT", self.peek_token())
|
||||
}
|
||||
|
@ -1333,6 +1348,15 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// parse the ESCAPE CHAR portion of LIKE, ILIKE, and SIMILAR TO
|
||||
pub fn parse_escape_char(&mut self) -> Result<Option<char>, ParserError> {
|
||||
if self.parse_keyword(Keyword::ESCAPE) {
|
||||
Ok(Some(self.parse_literal_char()?))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_array_index(&mut self, expr: Expr) -> Result<Expr, ParserError> {
|
||||
let index = self.parse_expr()?;
|
||||
self.expect_token(&Token::RBracket)?;
|
||||
|
@ -1463,6 +1487,7 @@ impl<'a> Parser<'a> {
|
|||
Token::Word(w) if w.keyword == Keyword::BETWEEN => Ok(Self::BETWEEN_PREC),
|
||||
Token::Word(w) if w.keyword == Keyword::LIKE => Ok(Self::BETWEEN_PREC),
|
||||
Token::Word(w) if w.keyword == Keyword::ILIKE => Ok(Self::BETWEEN_PREC),
|
||||
Token::Word(w) if w.keyword == Keyword::SIMILAR => Ok(Self::BETWEEN_PREC),
|
||||
_ => Ok(0),
|
||||
},
|
||||
Token::Word(w) if w.keyword == Keyword::IS => Ok(17),
|
||||
|
@ -1471,6 +1496,7 @@ impl<'a> Parser<'a> {
|
|||
Token::Word(w) if w.keyword == Keyword::LIKE => Ok(Self::BETWEEN_PREC),
|
||||
Token::Word(w) if w.keyword == Keyword::ILIKE => Ok(Self::BETWEEN_PREC),
|
||||
Token::Word(w) if w.keyword == Keyword::OPERATOR => Ok(Self::BETWEEN_PREC),
|
||||
Token::Word(w) if w.keyword == Keyword::SIMILAR => Ok(Self::BETWEEN_PREC),
|
||||
Token::Eq
|
||||
| Token::Lt
|
||||
| Token::LtEq
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue