mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-04 06:18:17 +00:00
Support mysql RLIKE
and REGEXP
binary operators (#1017)
This commit is contained in:
parent
88510f6625
commit
c03586b727
5 changed files with 53 additions and 3 deletions
|
@ -429,6 +429,14 @@ pub enum Expr {
|
|||
pattern: Box<Expr>,
|
||||
escape_char: Option<char>,
|
||||
},
|
||||
/// MySQL: RLIKE regex or REGEXP regex
|
||||
RLike {
|
||||
negated: bool,
|
||||
expr: Box<Expr>,
|
||||
pattern: Box<Expr>,
|
||||
// true for REGEXP, false for RLIKE (no difference in semantics)
|
||||
regexp: bool,
|
||||
},
|
||||
/// Any operation e.g. `foo > ANY(bar)`, comparison operator is one of [=, >, <, =>, =<, !=]
|
||||
AnyOp {
|
||||
left: Box<Expr>,
|
||||
|
@ -740,6 +748,19 @@ impl fmt::Display for Expr {
|
|||
pattern
|
||||
),
|
||||
},
|
||||
Expr::RLike {
|
||||
negated,
|
||||
expr,
|
||||
pattern,
|
||||
regexp,
|
||||
} => write!(
|
||||
f,
|
||||
"{} {}{} {}",
|
||||
expr,
|
||||
if *negated { "NOT " } else { "" },
|
||||
if *regexp { "REGEXP" } else { "RLIKE" },
|
||||
pattern
|
||||
),
|
||||
Expr::SimilarTo {
|
||||
negated,
|
||||
expr,
|
||||
|
|
|
@ -498,6 +498,7 @@ define_keywords!(
|
|||
REFERENCES,
|
||||
REFERENCING,
|
||||
REGCLASS,
|
||||
REGEXP,
|
||||
REGR_AVGX,
|
||||
REGR_AVGY,
|
||||
REGR_COUNT,
|
||||
|
@ -524,6 +525,7 @@ define_keywords!(
|
|||
RETURNS,
|
||||
REVOKE,
|
||||
RIGHT,
|
||||
RLIKE,
|
||||
ROLE,
|
||||
ROLLBACK,
|
||||
ROLLUP,
|
||||
|
|
|
@ -1932,10 +1932,21 @@ impl<'a> Parser<'a> {
|
|||
| Keyword::BETWEEN
|
||||
| Keyword::LIKE
|
||||
| Keyword::ILIKE
|
||||
| Keyword::SIMILAR => {
|
||||
| Keyword::SIMILAR
|
||||
| Keyword::REGEXP
|
||||
| Keyword::RLIKE => {
|
||||
self.prev_token();
|
||||
let negated = self.parse_keyword(Keyword::NOT);
|
||||
if self.parse_keyword(Keyword::IN) {
|
||||
let regexp = self.parse_keyword(Keyword::REGEXP);
|
||||
let rlike = self.parse_keyword(Keyword::RLIKE);
|
||||
if regexp || rlike {
|
||||
Ok(Expr::RLike {
|
||||
negated,
|
||||
expr: Box::new(expr),
|
||||
pattern: Box::new(self.parse_subexpr(Self::LIKE_PREC)?),
|
||||
regexp,
|
||||
})
|
||||
} else if self.parse_keyword(Keyword::IN) {
|
||||
self.parse_in(expr, negated)
|
||||
} else if self.parse_keyword(Keyword::BETWEEN) {
|
||||
self.parse_between(expr, negated)
|
||||
|
@ -2178,6 +2189,8 @@ 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::LIKE_PREC),
|
||||
Token::Word(w) if w.keyword == Keyword::ILIKE => Ok(Self::LIKE_PREC),
|
||||
Token::Word(w) if w.keyword == Keyword::RLIKE => Ok(Self::LIKE_PREC),
|
||||
Token::Word(w) if w.keyword == Keyword::REGEXP => Ok(Self::LIKE_PREC),
|
||||
Token::Word(w) if w.keyword == Keyword::SIMILAR => Ok(Self::LIKE_PREC),
|
||||
_ => Ok(0),
|
||||
},
|
||||
|
@ -2186,6 +2199,8 @@ 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::LIKE_PREC),
|
||||
Token::Word(w) if w.keyword == Keyword::ILIKE => Ok(Self::LIKE_PREC),
|
||||
Token::Word(w) if w.keyword == Keyword::RLIKE => Ok(Self::LIKE_PREC),
|
||||
Token::Word(w) if w.keyword == Keyword::REGEXP => Ok(Self::LIKE_PREC),
|
||||
Token::Word(w) if w.keyword == Keyword::SIMILAR => Ok(Self::LIKE_PREC),
|
||||
Token::Word(w) if w.keyword == Keyword::OPERATOR => Ok(Self::BETWEEN_PREC),
|
||||
Token::Word(w) if w.keyword == Keyword::DIV => Ok(Self::MUL_DIV_MOD_OP_PREC),
|
||||
|
|
|
@ -111,7 +111,7 @@ impl TestedDialects {
|
|||
/// 2. re-serializing the result of parsing `sql` produces the same
|
||||
/// `canonical` sql string
|
||||
pub fn one_statement_parses_to(&self, sql: &str, canonical: &str) -> Statement {
|
||||
let mut statements = self.parse_sql_statements(sql).unwrap();
|
||||
let mut statements = self.parse_sql_statements(sql).expect(sql);
|
||||
assert_eq!(statements.len(), 1);
|
||||
|
||||
if !canonical.is_empty() && sql != canonical {
|
||||
|
|
|
@ -1454,6 +1454,18 @@ fn parse_show_variables() {
|
|||
mysql_and_generic().verified_stmt("SHOW VARIABLES WHERE value = '3306'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_rlike_and_regexp() {
|
||||
for s in &[
|
||||
"SELECT 1 WHERE 'a' RLIKE '^a$'",
|
||||
"SELECT 1 WHERE 'a' REGEXP '^a$'",
|
||||
"SELECT 1 WHERE 'a' NOT RLIKE '^a$'",
|
||||
"SELECT 1 WHERE 'a' NOT REGEXP '^a$'",
|
||||
] {
|
||||
mysql_and_generic().verified_only_select(s);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_kill() {
|
||||
let stmt = mysql_and_generic().verified_stmt("KILL CONNECTION 5");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue