mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-07-07 17:04:59 +00:00
Merge pull request #300 from maxcountryman/feature/ilike
provide ILIKE support
This commit is contained in:
commit
35ef0eee38
5 changed files with 62 additions and 1 deletions
|
@ -1546,6 +1546,7 @@ impl fmt::Display for TransactionIsolationLevel {
|
|||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub enum ShowStatementFilter {
|
||||
Like(String),
|
||||
ILike(String),
|
||||
Where(Expr),
|
||||
}
|
||||
|
||||
|
@ -1554,6 +1555,7 @@ impl fmt::Display for ShowStatementFilter {
|
|||
use ShowStatementFilter::*;
|
||||
match self {
|
||||
Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
|
||||
ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
|
||||
Where(expr) => write!(f, "WHERE {}", expr),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,6 +72,8 @@ pub enum BinaryOperator {
|
|||
Or,
|
||||
Like,
|
||||
NotLike,
|
||||
ILike,
|
||||
NotILike,
|
||||
BitwiseOr,
|
||||
BitwiseAnd,
|
||||
BitwiseXor,
|
||||
|
@ -100,6 +102,8 @@ impl fmt::Display for BinaryOperator {
|
|||
BinaryOperator::Or => "OR",
|
||||
BinaryOperator::Like => "LIKE",
|
||||
BinaryOperator::NotLike => "NOT LIKE",
|
||||
BinaryOperator::ILike => "ILIKE",
|
||||
BinaryOperator::NotILike => "NOT ILIKE",
|
||||
BinaryOperator::BitwiseOr => "|",
|
||||
BinaryOperator::BitwiseAnd => "&",
|
||||
BinaryOperator::BitwiseXor => "^",
|
||||
|
|
|
@ -236,6 +236,7 @@ define_keywords!(
|
|||
IDENTITY,
|
||||
IF,
|
||||
IGNORE,
|
||||
ILIKE,
|
||||
IN,
|
||||
INDEX,
|
||||
INDICATOR,
|
||||
|
|
|
@ -839,9 +839,12 @@ impl<'a> Parser<'a> {
|
|||
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
|
||||
}
|
||||
|
@ -975,12 +978,14 @@ impl<'a> Parser<'a> {
|
|||
Token::Word(w) if w.keyword == Keyword::IN => Ok(Self::BETWEEN_PREC),
|
||||
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),
|
||||
_ => Ok(0),
|
||||
},
|
||||
Token::Word(w) if w.keyword == Keyword::IS => Ok(17),
|
||||
Token::Word(w) if w.keyword == Keyword::IN => Ok(Self::BETWEEN_PREC),
|
||||
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::Eq
|
||||
| Token::Lt
|
||||
| Token::LtEq
|
||||
|
@ -1472,7 +1477,7 @@ impl<'a> Parser<'a> {
|
|||
) -> Result<Statement, ParserError> {
|
||||
let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
|
||||
let table_name = self.parse_object_name()?;
|
||||
let like = if self.parse_keyword(Keyword::LIKE) {
|
||||
let like = if self.parse_keyword(Keyword::LIKE) || self.parse_keyword(Keyword::ILIKE) {
|
||||
self.parse_object_name().ok()
|
||||
} else {
|
||||
None
|
||||
|
@ -2497,6 +2502,10 @@ impl<'a> Parser<'a> {
|
|||
Ok(Some(ShowStatementFilter::Like(
|
||||
self.parse_literal_string()?,
|
||||
)))
|
||||
} else if self.parse_keyword(Keyword::ILIKE) {
|
||||
Ok(Some(ShowStatementFilter::ILike(
|
||||
self.parse_literal_string()?,
|
||||
)))
|
||||
} else if self.parse_keyword(Keyword::WHERE) {
|
||||
Ok(Some(ShowStatementFilter::Where(self.parse_expr()?)))
|
||||
} else {
|
||||
|
|
|
@ -687,6 +687,51 @@ fn parse_like() {
|
|||
chk(true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_ilike() {
|
||||
fn chk(negated: bool) {
|
||||
let sql = &format!(
|
||||
"SELECT * FROM customers WHERE name {}ILIKE '%a'",
|
||||
if negated { "NOT " } else { "" }
|
||||
);
|
||||
let select = verified_only_select(sql);
|
||||
assert_eq!(
|
||||
Expr::BinaryOp {
|
||||
left: Box::new(Expr::Identifier(Ident::new("name"))),
|
||||
op: if negated {
|
||||
BinaryOperator::NotILike
|
||||
} else {
|
||||
BinaryOperator::ILike
|
||||
},
|
||||
right: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))),
|
||||
},
|
||||
select.selection.unwrap()
|
||||
);
|
||||
|
||||
// This statement tests that LIKE and NOT LIKE have the same precedence.
|
||||
// This was previously mishandled (#81).
|
||||
let sql = &format!(
|
||||
"SELECT * FROM customers WHERE name {}ILIKE '%a' IS NULL",
|
||||
if negated { "NOT " } else { "" }
|
||||
);
|
||||
let select = verified_only_select(sql);
|
||||
assert_eq!(
|
||||
Expr::IsNull(Box::new(Expr::BinaryOp {
|
||||
left: Box::new(Expr::Identifier(Ident::new("name"))),
|
||||
op: if negated {
|
||||
BinaryOperator::NotILike
|
||||
} else {
|
||||
BinaryOperator::ILike
|
||||
},
|
||||
right: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))),
|
||||
})),
|
||||
select.selection.unwrap()
|
||||
);
|
||||
}
|
||||
chk(false);
|
||||
chk(true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_in_list() {
|
||||
fn chk(negated: bool) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue