Skip to content

Commit e849f7f

Browse files
authored
Add support for the LIKE ANY and ILIKE ANY pattern-matching condition (#1456)
1 parent 32a126b commit e849f7f

File tree

3 files changed

+36
-4
lines changed

3 files changed

+36
-4
lines changed

src/ast/mod.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -613,13 +613,19 @@ pub enum Expr {
613613
/// `[NOT] LIKE <pattern> [ESCAPE <escape_character>]`
614614
Like {
615615
negated: bool,
616+
// Snowflake supports the ANY keyword to match against a list of patterns
617+
// https://docs.snowflake.com/en/sql-reference/functions/like_any
618+
any: bool,
616619
expr: Box<Expr>,
617620
pattern: Box<Expr>,
618621
escape_char: Option<String>,
619622
},
620623
/// `ILIKE` (case-insensitive `LIKE`)
621624
ILike {
622625
negated: bool,
626+
// Snowflake supports the ANY keyword to match against a list of patterns
627+
// https://docs.snowflake.com/en/sql-reference/functions/like_any
628+
any: bool,
623629
expr: Box<Expr>,
624630
pattern: Box<Expr>,
625631
escape_char: Option<String>,
@@ -1242,20 +1248,23 @@ impl fmt::Display for Expr {
12421248
expr,
12431249
pattern,
12441250
escape_char,
1251+
any,
12451252
} => match escape_char {
12461253
Some(ch) => write!(
12471254
f,
1248-
"{} {}LIKE {} ESCAPE '{}'",
1255+
"{} {}LIKE {}{} ESCAPE '{}'",
12491256
expr,
12501257
if *negated { "NOT " } else { "" },
1258+
if *any { "ANY " } else { "" },
12511259
pattern,
12521260
ch
12531261
),
12541262
_ => write!(
12551263
f,
1256-
"{} {}LIKE {}",
1264+
"{} {}LIKE {}{}",
12571265
expr,
12581266
if *negated { "NOT " } else { "" },
1267+
if *any { "ANY " } else { "" },
12591268
pattern
12601269
),
12611270
},
@@ -1264,20 +1273,23 @@ impl fmt::Display for Expr {
12641273
expr,
12651274
pattern,
12661275
escape_char,
1276+
any,
12671277
} => match escape_char {
12681278
Some(ch) => write!(
12691279
f,
1270-
"{} {}ILIKE {} ESCAPE '{}'",
1280+
"{} {}ILIKE {}{} ESCAPE '{}'",
12711281
expr,
12721282
if *negated { "NOT " } else { "" },
1283+
if *any { "ANY" } else { "" },
12731284
pattern,
12741285
ch
12751286
),
12761287
_ => write!(
12771288
f,
1278-
"{} {}ILIKE {}",
1289+
"{} {}ILIKE {}{}",
12791290
expr,
12801291
if *negated { "NOT " } else { "" },
1292+
if *any { "ANY " } else { "" },
12811293
pattern
12821294
),
12831295
},

src/parser/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2749,6 +2749,7 @@ impl<'a> Parser<'a> {
27492749
} else if self.parse_keyword(Keyword::LIKE) {
27502750
Ok(Expr::Like {
27512751
negated,
2752+
any: self.parse_keyword(Keyword::ANY),
27522753
expr: Box::new(expr),
27532754
pattern: Box::new(
27542755
self.parse_subexpr(self.dialect.prec_value(Precedence::Like))?,
@@ -2758,6 +2759,7 @@ impl<'a> Parser<'a> {
27582759
} else if self.parse_keyword(Keyword::ILIKE) {
27592760
Ok(Expr::ILike {
27602761
negated,
2762+
any: self.parse_keyword(Keyword::ANY),
27612763
expr: Box::new(expr),
27622764
pattern: Box::new(
27632765
self.parse_subexpr(self.dialect.prec_value(Precedence::Like))?,

tests/sqlparser_common.rs

+18
Original file line numberDiff line numberDiff line change
@@ -1550,6 +1550,7 @@ fn parse_not_precedence() {
15501550
negated: true,
15511551
pattern: Box::new(Expr::Value(Value::SingleQuotedString("b".into()))),
15521552
escape_char: None,
1553+
any: false,
15531554
}),
15541555
},
15551556
);
@@ -1580,6 +1581,7 @@ fn parse_null_like() {
15801581
SelectItem::ExprWithAlias {
15811582
expr: Expr::Like {
15821583
expr: Box::new(Expr::Identifier(Ident::new("column1"))),
1584+
any: false,
15831585
negated: false,
15841586
pattern: Box::new(Expr::Value(Value::Null)),
15851587
escape_char: None,
@@ -1595,6 +1597,7 @@ fn parse_null_like() {
15951597
SelectItem::ExprWithAlias {
15961598
expr: Expr::Like {
15971599
expr: Box::new(Expr::Value(Value::Null)),
1600+
any: false,
15981601
negated: false,
15991602
pattern: Box::new(Expr::Identifier(Ident::new("column1"))),
16001603
escape_char: None,
@@ -1622,6 +1625,7 @@ fn parse_ilike() {
16221625
negated,
16231626
pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))),
16241627
escape_char: None,
1628+
any: false,
16251629
},
16261630
select.selection.unwrap()
16271631
);
@@ -1638,6 +1642,7 @@ fn parse_ilike() {
16381642
negated,
16391643
pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))),
16401644
escape_char: Some('^'.to_string()),
1645+
any: false,
16411646
},
16421647
select.selection.unwrap()
16431648
);
@@ -1655,6 +1660,7 @@ fn parse_ilike() {
16551660
negated,
16561661
pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))),
16571662
escape_char: None,
1663+
any: false,
16581664
})),
16591665
select.selection.unwrap()
16601666
);
@@ -1677,6 +1683,7 @@ fn parse_like() {
16771683
negated,
16781684
pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))),
16791685
escape_char: None,
1686+
any: false,
16801687
},
16811688
select.selection.unwrap()
16821689
);
@@ -1693,6 +1700,7 @@ fn parse_like() {
16931700
negated,
16941701
pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))),
16951702
escape_char: Some('^'.to_string()),
1703+
any: false,
16961704
},
16971705
select.selection.unwrap()
16981706
);
@@ -1710,6 +1718,7 @@ fn parse_like() {
17101718
negated,
17111719
pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))),
17121720
escape_char: None,
1721+
any: false,
17131722
})),
17141723
select.selection.unwrap()
17151724
);
@@ -10130,6 +10139,7 @@ fn test_selective_aggregation() {
1013010139
expr: Box::new(Expr::Identifier(Ident::new("name"))),
1013110140
pattern: Box::new(Expr::Value(Value::SingleQuotedString("a%".to_owned()))),
1013210141
escape_char: None,
10142+
any: false,
1013310143
})),
1013410144
null_treatment: None,
1013510145
over: None,
@@ -11291,3 +11301,11 @@ fn test_alter_policy() {
1129111301
"sql parser error: Expected: (, found: EOF"
1129211302
);
1129311303
}
11304+
11305+
#[test]
11306+
fn test_select_where_with_like_or_ilike_any() {
11307+
verified_stmt(r#"SELECT * FROM x WHERE a ILIKE ANY '%abc%'"#);
11308+
verified_stmt(r#"SELECT * FROM x WHERE a LIKE ANY '%abc%'"#);
11309+
verified_stmt(r#"SELECT * FROM x WHERE a ILIKE ANY ('%Jo%oe%', 'T%e')"#);
11310+
verified_stmt(r#"SELECT * FROM x WHERE a LIKE ANY ('%Jo%oe%', 'T%e')"#);
11311+
}

0 commit comments

Comments
 (0)