Skip to content

Commit 7816f98

Browse files
committed
sql_parser: glob|regexp|match expression refactored
1 parent e25dbe1 commit 7816f98

File tree

2 files changed

+119
-76
lines changed

2 files changed

+119
-76
lines changed

src/ast/expression/mod.rs

+48-12
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,13 @@ pub enum Expression {
5151
LikeExpression(LikeExpressionType),
5252

5353
/// Glob
54-
GlobExpression(Box<Expression>),
54+
GlobExpression(GlobExpression),
5555

5656
/// Regexp
57-
RegexpExpression(Box<Expression>),
57+
RegexpExpression(RegexpMatchingExpression),
5858

5959
/// Match
60-
MatchExpression(Box<Expression>),
60+
MatchExpression(MatchExpression),
6161

6262
/// Is
6363
IsExpression(AnIsExpression),
@@ -150,15 +150,6 @@ pub enum BinaryMatchingExpression {
150150
/// For NOT $BinaryMatchingExpression use cases
151151
Not(Box<BinaryMatchingExpression>),
152152

153-
/// Glob
154-
Glob(Box<Expression>),
155-
156-
/// Regexp
157-
Regexp(Box<Expression>),
158-
159-
/// Match
160-
Match(Box<Expression>),
161-
162153
/// Is
163154
Is(AnIsExpression),
164155

@@ -191,6 +182,51 @@ impl From<LikeExpressionType> for Expression {
191182
}
192183
}
193184

185+
#[derive(Debug, PartialEq, Clone)]
186+
pub struct GlobExpression {
187+
pub expression: Box<Expression>,
188+
189+
pub not: bool,
190+
191+
pub pattern: Box<Expression>,
192+
}
193+
194+
impl From<GlobExpression> for Expression {
195+
fn from(glob_expr: GlobExpression) -> Self {
196+
Expression::GlobExpression(glob_expr)
197+
}
198+
}
199+
200+
#[derive(Debug, PartialEq, Clone)]
201+
pub struct RegexpMatchingExpression {
202+
pub expression: Box<Expression>,
203+
204+
pub not: bool,
205+
206+
pub pattern: Box<Expression>,
207+
}
208+
209+
impl From<RegexpMatchingExpression> for Expression {
210+
fn from(regexp_expr: RegexpMatchingExpression) -> Self {
211+
Expression::RegexpExpression(regexp_expr)
212+
}
213+
}
214+
215+
#[derive(Debug, PartialEq, Clone)]
216+
pub struct MatchExpression {
217+
pub expression: Box<Expression>,
218+
219+
pub not: bool,
220+
221+
pub pattern: Box<Expression>,
222+
}
223+
224+
impl From<MatchExpression> for Expression {
225+
fn from(match_expr: MatchExpression) -> Self {
226+
Expression::MatchExpression(match_expr)
227+
}
228+
}
229+
194230
/// An IS expression
195231
#[derive(Debug, PartialEq, Clone)]
196232
pub struct AnIsExpression {
+71-64
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::parser::errors::ParsingError;
2-
use crate::{BinaryMatchingExpression, Expression, Keyword, Parser};
2+
use crate::{
3+
Expression, GlobExpression, Keyword, MatchExpression, Parser, RegexpMatchingExpression,
4+
};
35

46
use super::ExpressionParser;
57

@@ -30,91 +32,96 @@ impl RegexpMatchExpressionParser for Parser<'_> {
3032
let pattern = self.parse_expression()?;
3133

3234
let matching_expression = match match_type {
33-
Keyword::Glob => BinaryMatchingExpression::Glob(Box::new(pattern)),
34-
Keyword::Regexp => BinaryMatchingExpression::Regexp(Box::new(pattern)),
35-
Keyword::Match => BinaryMatchingExpression::Match(Box::new(pattern)),
35+
Keyword::Glob => Expression::GlobExpression(GlobExpression {
36+
expression: Box::new(expression),
37+
not: is_not,
38+
pattern: Box::new(pattern),
39+
}),
40+
Keyword::Regexp => Expression::RegexpExpression(RegexpMatchingExpression {
41+
expression: Box::new(expression),
42+
not: is_not,
43+
pattern: Box::new(pattern),
44+
}),
45+
Keyword::Match => Expression::MatchExpression(MatchExpression {
46+
expression: Box::new(expression),
47+
not: is_not,
48+
pattern: Box::new(pattern),
49+
}),
3650
_ => unreachable!(),
3751
};
3852

39-
if is_not {
40-
Ok(Expression::BinaryMatchingExpression(
41-
Box::new(expression),
42-
BinaryMatchingExpression::Not(Box::new(matching_expression)),
43-
))
44-
} else {
45-
Ok(Expression::BinaryMatchingExpression(
46-
Box::new(expression),
47-
matching_expression,
48-
))
49-
}
53+
Ok(matching_expression)
5054
}
5155
}
5256

5357
#[cfg(test)]
5458
mod regexp_match_expression_tests {
5559
use crate::parser::test_utils::run_sunny_day_test;
5660
use crate::select::test_utils::select_expr;
57-
use crate::{BinaryMatchingExpression, Expression, Keyword};
61+
use crate::{Expression, GlobExpression, MatchExpression, RegexpMatchingExpression};
5862

5963
use crate::parser::expression::test_utils::*;
6064

61-
fn binary_matching_expr(pattern: Expression, keyword: Keyword) -> BinaryMatchingExpression {
62-
match keyword {
63-
Keyword::Glob => BinaryMatchingExpression::Glob(Box::new(pattern)),
64-
Keyword::Regexp => BinaryMatchingExpression::Regexp(Box::new(pattern)),
65-
Keyword::Match => BinaryMatchingExpression::Match(Box::new(pattern)),
66-
_ => panic!("Invalid keyword: {}", keyword),
65+
fn glob_expr(expression: Expression, pattern: Expression) -> GlobExpression {
66+
GlobExpression {
67+
expression: Box::new(expression),
68+
not: false,
69+
pattern: Box::new(pattern),
6770
}
6871
}
6972

70-
fn regexp_match_expr(
71-
expression: Expression,
72-
pattern: Expression,
73-
keyword: Keyword,
74-
is_not: bool,
75-
) -> Expression {
76-
let binary_matching_expression = if is_not {
77-
BinaryMatchingExpression::Not(Box::new(binary_matching_expr(pattern, keyword)))
78-
} else {
79-
binary_matching_expr(pattern, keyword)
80-
};
73+
fn regexp_expr(expression: Expression, pattern: Expression) -> RegexpMatchingExpression {
74+
RegexpMatchingExpression {
75+
expression: Box::new(expression),
76+
not: false,
77+
pattern: Box::new(pattern),
78+
}
79+
}
8180

82-
Expression::BinaryMatchingExpression(Box::new(expression), binary_matching_expression)
81+
fn match_expr(expression: Expression, pattern: Expression) -> MatchExpression {
82+
MatchExpression {
83+
expression: Box::new(expression),
84+
not: false,
85+
pattern: Box::new(pattern),
86+
}
8387
}
8488

8589
#[test]
86-
fn regexp_match() {
87-
let keywords = vec![Keyword::Glob, Keyword::Regexp, Keyword::Match];
88-
89-
for keyword in keywords {
90-
run_sunny_day_test(
91-
&format!("SELECT 1 {} 'a*';", keyword),
92-
select_expr(regexp_match_expr(
93-
numeric_expr("1"),
94-
string_expr("'a*'"),
95-
keyword,
96-
false,
97-
))
98-
.into(),
99-
);
100-
}
90+
fn glob_expr_test() {
91+
let expected = glob_expr(numeric_expr("1"), string_expr("'a*'"));
92+
run_sunny_day_test("SELECT 1 GLOB 'a*';", select_expr(expected.into()).into());
93+
94+
let mut expected = glob_expr(numeric_expr("1"), string_expr("'a*'"));
95+
expected.not = true;
96+
run_sunny_day_test(
97+
"SELECT 1 NOT GLOB 'a*';",
98+
select_expr(expected.into()).into(),
99+
);
101100
}
102101

103102
#[test]
104-
fn not_regexp_match() {
105-
let keywords = vec![Keyword::Glob, Keyword::Regexp, Keyword::Match];
106-
107-
for keyword in keywords {
108-
run_sunny_day_test(
109-
&format!("SELECT 1 NOT {} 'a*';", keyword),
110-
select_expr(regexp_match_expr(
111-
numeric_expr("1"),
112-
string_expr("'a*'"),
113-
keyword,
114-
true,
115-
))
116-
.into(),
117-
);
118-
}
103+
fn regexp_expr_test() {
104+
let expected = regexp_expr(numeric_expr("1"), string_expr("'a*'"));
105+
run_sunny_day_test("SELECT 1 REGEXP 'a*';", select_expr(expected.into()).into());
106+
107+
let mut expected = regexp_expr(numeric_expr("1"), string_expr("'a*'"));
108+
expected.not = true;
109+
run_sunny_day_test(
110+
"SELECT 1 NOT REGEXP 'a*';",
111+
select_expr(expected.into()).into(),
112+
);
113+
}
114+
115+
#[test]
116+
fn match_expr_test() {
117+
let expected = match_expr(numeric_expr("1"), string_expr("'a*'"));
118+
run_sunny_day_test("SELECT 1 MATCH 'a*';", select_expr(expected.into()).into());
119+
120+
let mut expected = match_expr(numeric_expr("1"), string_expr("'a*'"));
121+
expected.not = true;
122+
run_sunny_day_test(
123+
"SELECT 1 NOT MATCH 'a*';",
124+
select_expr(expected.into()).into(),
125+
);
119126
}
120127
}

0 commit comments

Comments
 (0)