Skip to content

Commit 311deaa

Browse files
committed
1 parent ac1c339 commit 311deaa

File tree

4 files changed

+60
-1
lines changed

4 files changed

+60
-1
lines changed

src/ast/operator.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ pub enum BinaryOperator {
139139
DuckIntegerDivide,
140140
/// MySQL [`DIV`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html) integer division
141141
MyIntegerDivide,
142+
/// MATCH operator, e.g. `a MATCH b` (SQLite-specific)
143+
/// See <https://www.sqlite.org/lang_expr.html#the_like_glob_regexp_match_and_extract_operators>
144+
Match,
145+
/// REGEXP operator, e.g. `a REGEXP b` (SQLite-specific)
146+
Regexp,
142147
/// Support for custom operators (such as Postgres custom operators)
143148
Custom(String),
144149
/// Bitwise XOR, e.g. `a # b` (PostgreSQL-specific)
@@ -350,6 +355,8 @@ impl fmt::Display for BinaryOperator {
350355
BinaryOperator::BitwiseXor => f.write_str("^"),
351356
BinaryOperator::DuckIntegerDivide => f.write_str("//"),
352357
BinaryOperator::MyIntegerDivide => f.write_str("DIV"),
358+
BinaryOperator::Match => f.write_str("MATCH"),
359+
BinaryOperator::Regexp => f.write_str("REGEXP"),
353360
BinaryOperator::Custom(s) => f.write_str(s),
354361
BinaryOperator::PGBitwiseXor => f.write_str("#"),
355362
BinaryOperator::PGBitwiseShiftLeft => f.write_str("<<"),

src/dialect/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,7 @@ pub trait Dialect: Debug + Any {
619619
Token::Word(w) if w.keyword == Keyword::ILIKE => Ok(p!(Like)),
620620
Token::Word(w) if w.keyword == Keyword::RLIKE => Ok(p!(Like)),
621621
Token::Word(w) if w.keyword == Keyword::REGEXP => Ok(p!(Like)),
622+
Token::Word(w) if w.keyword == Keyword::MATCH => Ok(p!(Like)),
622623
Token::Word(w) if w.keyword == Keyword::SIMILAR => Ok(p!(Like)),
623624
_ => Ok(self.prec_unknown()),
624625
},
@@ -630,6 +631,7 @@ pub trait Dialect: Debug + Any {
630631
Token::Word(w) if w.keyword == Keyword::ILIKE => Ok(p!(Like)),
631632
Token::Word(w) if w.keyword == Keyword::RLIKE => Ok(p!(Like)),
632633
Token::Word(w) if w.keyword == Keyword::REGEXP => Ok(p!(Like)),
634+
Token::Word(w) if w.keyword == Keyword::MATCH => Ok(p!(Like)),
633635
Token::Word(w) if w.keyword == Keyword::SIMILAR => Ok(p!(Like)),
634636
Token::Word(w) if w.keyword == Keyword::OPERATOR => Ok(p!(Between)),
635637
Token::Word(w) if w.keyword == Keyword::DIV => Ok(p!(MulDivModOp)),

src/dialect/sqlite.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18-
use crate::ast::Statement;
18+
use crate::ast::BinaryOperator;
19+
use crate::ast::{Expr, Statement};
1920
use crate::dialect::Dialect;
2021
use crate::keywords::Keyword;
2122
use crate::parser::{Parser, ParserError};
@@ -70,6 +71,27 @@ impl Dialect for SQLiteDialect {
7071
}
7172
}
7273

74+
fn parse_infix(
75+
&self,
76+
parser: &mut crate::parser::Parser,
77+
expr: &crate::ast::Expr,
78+
_precedence: u8,
79+
) -> Option<Result<crate::ast::Expr, ParserError>> {
80+
// Parse MATCH and REGEXP as operators
81+
// See <https://www.sqlite.org/lang_expr.html#the_like_glob_regexp_match_and_extract_operators>
82+
for (keyword, op) in [
83+
(Keyword::REGEXP, BinaryOperator::Regexp),
84+
(Keyword::MATCH, BinaryOperator::Match),
85+
] {
86+
if parser.parse_keyword(keyword) {
87+
let left = Box::new(expr.clone());
88+
let right = Box::new(parser.parse_expr().unwrap());
89+
return Some(Ok(Expr::BinaryOp { left, op, right }));
90+
}
91+
}
92+
None
93+
}
94+
7395
fn supports_in_empty_list(&self) -> bool {
7496
true
7597
}

tests/sqlparser_sqlite.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,34 @@ fn test_dollar_identifier_as_placeholder() {
562562
}
563563
}
564564

565+
#[test]
566+
fn test_match_operator() {
567+
assert_eq!(
568+
sqlite().verified_expr("col MATCH 'pattern'"),
569+
Expr::BinaryOp {
570+
op: BinaryOperator::Match,
571+
left: Box::new(Expr::Identifier(Ident::new("col"))),
572+
right: Box::new(Expr::Value(
573+
(Value::SingleQuotedString("pattern".to_string())).with_empty_span()
574+
))
575+
}
576+
);
577+
}
578+
579+
#[test]
580+
fn test_regexp_operator() {
581+
assert_eq!(
582+
sqlite().verified_expr("col REGEXP 'pattern'"),
583+
Expr::BinaryOp {
584+
op: BinaryOperator::Regexp,
585+
left: Box::new(Expr::Identifier(Ident::new("col"))),
586+
right: Box::new(Expr::Value(
587+
(Value::SingleQuotedString("pattern".to_string())).with_empty_span()
588+
))
589+
}
590+
);
591+
}
592+
565593
fn sqlite() -> TestedDialects {
566594
TestedDialects::new(vec![Box::new(SQLiteDialect {})])
567595
}

0 commit comments

Comments
 (0)