Skip to content

Commit

Permalink
Add support for the LIKE ANY and ILIKE ANY pattern-matching condition (
Browse files Browse the repository at this point in the history
  • Loading branch information
yoavcloud authored Oct 4, 2024
1 parent 32a126b commit e849f7f
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 4 deletions.
20 changes: 16 additions & 4 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -613,13 +613,19 @@ pub enum Expr {
/// `[NOT] LIKE <pattern> [ESCAPE <escape_character>]`
Like {
negated: bool,
// Snowflake supports the ANY keyword to match against a list of patterns
// https://docs.snowflake.com/en/sql-reference/functions/like_any
any: bool,
expr: Box<Expr>,
pattern: Box<Expr>,
escape_char: Option<String>,
},
/// `ILIKE` (case-insensitive `LIKE`)
ILike {
negated: bool,
// Snowflake supports the ANY keyword to match against a list of patterns
// https://docs.snowflake.com/en/sql-reference/functions/like_any
any: bool,
expr: Box<Expr>,
pattern: Box<Expr>,
escape_char: Option<String>,
Expand Down Expand Up @@ -1242,20 +1248,23 @@ impl fmt::Display for Expr {
expr,
pattern,
escape_char,
any,
} => match escape_char {
Some(ch) => write!(
f,
"{} {}LIKE {} ESCAPE '{}'",
"{} {}LIKE {}{} ESCAPE '{}'",
expr,
if *negated { "NOT " } else { "" },
if *any { "ANY " } else { "" },
pattern,
ch
),
_ => write!(
f,
"{} {}LIKE {}",
"{} {}LIKE {}{}",
expr,
if *negated { "NOT " } else { "" },
if *any { "ANY " } else { "" },
pattern
),
},
Expand All @@ -1264,20 +1273,23 @@ impl fmt::Display for Expr {
expr,
pattern,
escape_char,
any,
} => match escape_char {
Some(ch) => write!(
f,
"{} {}ILIKE {} ESCAPE '{}'",
"{} {}ILIKE {}{} ESCAPE '{}'",
expr,
if *negated { "NOT " } else { "" },
if *any { "ANY" } else { "" },
pattern,
ch
),
_ => write!(
f,
"{} {}ILIKE {}",
"{} {}ILIKE {}{}",
expr,
if *negated { "NOT " } else { "" },
if *any { "ANY " } else { "" },
pattern
),
},
Expand Down
2 changes: 2 additions & 0 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2749,6 +2749,7 @@ impl<'a> Parser<'a> {
} else if self.parse_keyword(Keyword::LIKE) {
Ok(Expr::Like {
negated,
any: self.parse_keyword(Keyword::ANY),
expr: Box::new(expr),
pattern: Box::new(
self.parse_subexpr(self.dialect.prec_value(Precedence::Like))?,
Expand All @@ -2758,6 +2759,7 @@ impl<'a> Parser<'a> {
} else if self.parse_keyword(Keyword::ILIKE) {
Ok(Expr::ILike {
negated,
any: self.parse_keyword(Keyword::ANY),
expr: Box::new(expr),
pattern: Box::new(
self.parse_subexpr(self.dialect.prec_value(Precedence::Like))?,
Expand Down
18 changes: 18 additions & 0 deletions tests/sqlparser_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1550,6 +1550,7 @@ fn parse_not_precedence() {
negated: true,
pattern: Box::new(Expr::Value(Value::SingleQuotedString("b".into()))),
escape_char: None,
any: false,
}),
},
);
Expand Down Expand Up @@ -1580,6 +1581,7 @@ fn parse_null_like() {
SelectItem::ExprWithAlias {
expr: Expr::Like {
expr: Box::new(Expr::Identifier(Ident::new("column1"))),
any: false,
negated: false,
pattern: Box::new(Expr::Value(Value::Null)),
escape_char: None,
Expand All @@ -1595,6 +1597,7 @@ fn parse_null_like() {
SelectItem::ExprWithAlias {
expr: Expr::Like {
expr: Box::new(Expr::Value(Value::Null)),
any: false,
negated: false,
pattern: Box::new(Expr::Identifier(Ident::new("column1"))),
escape_char: None,
Expand Down Expand Up @@ -1622,6 +1625,7 @@ fn parse_ilike() {
negated,
pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))),
escape_char: None,
any: false,
},
select.selection.unwrap()
);
Expand All @@ -1638,6 +1642,7 @@ fn parse_ilike() {
negated,
pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))),
escape_char: Some('^'.to_string()),
any: false,
},
select.selection.unwrap()
);
Expand All @@ -1655,6 +1660,7 @@ fn parse_ilike() {
negated,
pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))),
escape_char: None,
any: false,
})),
select.selection.unwrap()
);
Expand All @@ -1677,6 +1683,7 @@ fn parse_like() {
negated,
pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))),
escape_char: None,
any: false,
},
select.selection.unwrap()
);
Expand All @@ -1693,6 +1700,7 @@ fn parse_like() {
negated,
pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))),
escape_char: Some('^'.to_string()),
any: false,
},
select.selection.unwrap()
);
Expand All @@ -1710,6 +1718,7 @@ fn parse_like() {
negated,
pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))),
escape_char: None,
any: false,
})),
select.selection.unwrap()
);
Expand Down Expand Up @@ -10130,6 +10139,7 @@ fn test_selective_aggregation() {
expr: Box::new(Expr::Identifier(Ident::new("name"))),
pattern: Box::new(Expr::Value(Value::SingleQuotedString("a%".to_owned()))),
escape_char: None,
any: false,
})),
null_treatment: None,
over: None,
Expand Down Expand Up @@ -11291,3 +11301,11 @@ fn test_alter_policy() {
"sql parser error: Expected: (, found: EOF"
);
}

#[test]
fn test_select_where_with_like_or_ilike_any() {
verified_stmt(r#"SELECT * FROM x WHERE a ILIKE ANY '%abc%'"#);
verified_stmt(r#"SELECT * FROM x WHERE a LIKE ANY '%abc%'"#);
verified_stmt(r#"SELECT * FROM x WHERE a ILIKE ANY ('%Jo%oe%', 'T%e')"#);
verified_stmt(r#"SELECT * FROM x WHERE a LIKE ANY ('%Jo%oe%', 'T%e')"#);
}

0 comments on commit e849f7f

Please sign in to comment.