From 346114554e44b3482730834399ad7188cb840739 Mon Sep 17 00:00:00 2001 From: jhspetersson Date: Thu, 30 Nov 2023 23:34:19 +0100 Subject: support BETWEEN operator #139 --- src/lexer.rs | 19 ++++++++++++++++++- src/operators.rs | 5 +++++ src/parser.rs | 28 ++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/lexer.rs b/src/lexer.rs index cecca2f..2f47b92 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -151,7 +151,8 @@ impl<'a> Lexer<'a> { "limit" => Some(Lexem::Limit), "into" => Some(Lexem::Into), "eq" | "ne" | "gt" | "lt" | "ge" | "le" | "gte" | "lte" | - "regexp" | "rx" | "like" => Some(Lexem::Operator(s)), + "regexp" | "rx" | "like" | + "between" => Some(Lexem::Operator(s)), "mul" | "div" | "mod" | "plus" | "minus" => Some(Lexem::ArithmeticOperator(s)), _ => Some(Lexem::RawString(s)), } @@ -581,4 +582,20 @@ mod tests { assert_eq!(lexer.next_lexem(), Some(Lexem::By)); assert_eq!(lexer.next_lexem(), Some(Lexem::RawString(String::from("mime")))); } + + #[test] + fn between_op() { + let mut lexer = Lexer::new("select name from /home/user where size between 1000000 and 2000000"); + + assert_eq!(lexer.next_lexem(), Some(Lexem::RawString(String::from("select")))); + assert_eq!(lexer.next_lexem(), Some(Lexem::RawString(String::from("name")))); + assert_eq!(lexer.next_lexem(), Some(Lexem::From)); + assert_eq!(lexer.next_lexem(), Some(Lexem::RawString(String::from("/home/user")))); + assert_eq!(lexer.next_lexem(), Some(Lexem::Where)); + assert_eq!(lexer.next_lexem(), Some(Lexem::RawString(String::from("size")))); + assert_eq!(lexer.next_lexem(), Some(Lexem::Operator(String::from("between")))); + assert_eq!(lexer.next_lexem(), Some(Lexem::RawString(String::from("1000000")))); + assert_eq!(lexer.next_lexem(), Some(Lexem::And)); + assert_eq!(lexer.next_lexem(), Some(Lexem::RawString(String::from("2000000")))); + } } diff --git a/src/operators.rs b/src/operators.rs index 1df9fb5..759dfe6 100644 --- a/src/operators.rs +++ b/src/operators.rs @@ -20,6 +20,8 @@ pub enum Op { NotRx, Like, NotLike, + Between, + NotBetween, } impl Op { @@ -37,6 +39,7 @@ impl Op { "!=~" | "!~=" | "notrx" => Some(Op::NotRx), "like" => Some(Op::Like), "notlike" => Some(Op::NotLike), + "between" => Some(Op::Between), _ => None } } @@ -65,6 +68,8 @@ impl Op { Op::NotRx => Op::Rx, Op::Like => Op::NotLike, Op::NotLike => Op::Like, + Op::Between => Op::NotBetween, + Op::NotBetween => Op::Between, } } } diff --git a/src/parser.rs b/src/parser.rs index 3b3eb18..7f0aaca 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -481,6 +481,21 @@ impl Parser { let lexem = self.next_lexem(); let mut result = match lexem { + Some(Lexem::Operator(s)) if s.as_str() == "between" => { + let left_between = self.parse_add_sub()?; + + let and_lexem = self.next_lexem(); + if and_lexem.is_none() || and_lexem.unwrap() != Lexem::And { + return Err(String::from("Error parsing BETWEEN operator")) + } + + let right_between = self.parse_add_sub()?; + + let left_expr = Expr::op(left.clone().unwrap(), match not { false => Op::Gte, true => Op::Lte }, left_between.unwrap()); + let right_expr = Expr::op(left.unwrap(), match not { false => Op::Lte, true => Op::Gte }, right_between.unwrap()); + + Ok(Some(Expr::logical_op(left_expr, match not { false => LogicalOp::And, true => LogicalOp::Or }, right_expr))) + }, Some(Lexem::Operator(s)) => { let right = self.parse_add_sub()?; let op = Op::from_with_not(s, not); @@ -1146,4 +1161,17 @@ mod tests { assert_eq!(query.grouping_fields, Rc::new(vec![Expr::field(Field::Mime)])); } + + #[test] + fn query_with_between() { + let query = "select name, size from /test where size between 5mb and 6mb"; + let mut p = Parser::new(); + let query = p.parse(&query, false).unwrap(); + + let query2 = "select name, size from /test where size gte 5mb and size lte 6mb"; + let mut p2 = Parser::new(); + let query2 = p2.parse(&query2, false).unwrap(); + + assert_eq!(query.expr, query2.expr); + } } -- cgit v1.2.3