Skip to content

Commit 92d8490

Browse files
dyyms705
authored andcommitted
Correctly parse NOT IN
"A not in(..)" and "not predicate" is different.
1 parent 9e778b7 commit 92d8490

File tree

2 files changed

+48
-41
lines changed

2 files changed

+48
-41
lines changed

src/common.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ pub enum Operator {
217217
Less,
218218
LessOrEqual,
219219
In,
220+
NotIn,
220221
Is,
221222
}
222223

@@ -235,6 +236,7 @@ impl Display for Operator {
235236
Operator::Less => "<",
236237
Operator::LessOrEqual => "<=",
237238
Operator::In => "IN",
239+
Operator::NotIn => "NOT IN",
238240
Operator::Is => "IS",
239241
};
240242
write!(f, "{}", op)

src/condition.rs

Lines changed: 46 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,35 @@ fn is_null(i: &[u8]) -> IResult<&[u8], (Operator, ConditionExpression)> {
221221
))
222222
}
223223

224+
fn in_operation(i: &[u8]) -> IResult<&[u8], (Operator, ConditionExpression)> {
225+
map(
226+
separated_pair(
227+
opt(terminated(tag_no_case("not"), multispace1)),
228+
terminated(tag_no_case("in"), multispace0),
229+
alt((
230+
map(delimited(tag("("), nested_selection, tag(")")), |s| {
231+
ConditionBase::NestedSelect(Box::new(s))
232+
}),
233+
map(delimited(tag("("), value_list, tag(")")), |vs| {
234+
ConditionBase::LiteralList(vs)
235+
}),
236+
)),
237+
),
238+
|p| {
239+
let nested = ConditionExpression::Base(p.1);
240+
if (p.0).is_some() {
241+
(Operator::NotIn, nested)
242+
} else {
243+
(Operator::In, nested)
244+
}
245+
},
246+
)(i)
247+
}
248+
224249
fn boolean_primary_rest(i: &[u8]) -> IResult<&[u8], (Operator, ConditionExpression)> {
225250
alt((
226251
is_null,
252+
in_operation,
227253
separated_pair(binary_comparison_operator, multispace0, predicate),
228254
))(i)
229255
}
@@ -245,36 +271,6 @@ fn boolean_primary(i: &[u8]) -> IResult<&[u8], ConditionExpression> {
245271
}
246272

247273
fn predicate(i: &[u8]) -> IResult<&[u8], ConditionExpression> {
248-
let nested_sel_pred = map(
249-
separated_pair(
250-
opt(preceded(multispace0, tag_no_case("not"))),
251-
delimited(multispace1, tag_no_case("in"), multispace1),
252-
nested_selection,
253-
),
254-
|p| {
255-
let nested = ConditionExpression::Base(ConditionBase::NestedSelect(Box::new(p.1)));
256-
if (p.0).is_some() {
257-
ConditionExpression::NegationOp(Box::new(nested))
258-
} else {
259-
nested
260-
}
261-
},
262-
);
263-
let in_list_pred = map(
264-
separated_pair(
265-
opt(preceded(multispace0, tag_no_case("not"))),
266-
delimited(multispace1, tag_no_case("in"), multispace1),
267-
delimited(tag("("), value_list, tag(")")),
268-
),
269-
|p| {
270-
let list = ConditionExpression::Base(ConditionBase::LiteralList(p.1));
271-
if (p.0).is_some() {
272-
ConditionExpression::NegationOp(Box::new(list))
273-
} else {
274-
list
275-
}
276-
},
277-
);
278274
let nested_exists = map(
279275
tuple((
280276
opt(delimited(multispace0, tag_no_case("not"), multispace1)),
@@ -296,17 +292,7 @@ fn predicate(i: &[u8]) -> IResult<&[u8], ConditionExpression> {
296292
);
297293

298294
alt((
299-
map(
300-
pair(simple_expr, opt(alt((nested_sel_pred, in_list_pred)))),
301-
|p| match p.1 {
302-
Some(right) => ConditionExpression::ComparisonOp(ConditionTree {
303-
operator: Operator::In,
304-
left: Box::new(p.0),
305-
right: Box::new(right),
306-
}),
307-
None => p.0,
308-
},
309-
),
295+
simple_expr,
310296
nested_exists,
311297
))(i)
312298
}
@@ -960,4 +946,23 @@ mod tests {
960946
let res = res.unwrap().1;
961947
assert_eq!(res, expected);
962948
}
949+
950+
#[test]
951+
fn not_in_comparison() {
952+
use ConditionBase::*;
953+
954+
let qs1 = b"id not in (1,2)";
955+
let res1 = condition_expr(qs1);
956+
957+
let c1 = res1.unwrap().1;
958+
let expected1 = flat_condition_tree(
959+
Operator::NotIn,
960+
Field("id".into()),
961+
LiteralList(vec![1.into(), 2.into()]),
962+
);
963+
assert_eq!(c1, expected1);
964+
965+
let expected1 = "id NOT IN (1, 2)";
966+
assert_eq!(format!("{}", c1), expected1);
967+
}
963968
}

0 commit comments

Comments
 (0)