Skip to content

Commit 7bcbc43

Browse files
authored
feat: support within filter (#15)
1 parent 54a267a commit 7bcbc43

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,6 @@ Cargo.lock
1616
.vscode
1717

1818
*.swp
19+
20+
# Mac DS_Store
21+
**/*.DS_Store

src/parser/mod.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,7 @@ impl<'a> Parser<'a> {
867867
let mut expr = self.parse_prefix()?;
868868
debug!("prefix: {:?}", expr);
869869
loop {
870+
expr = self.parse_within_filter(expr)?;
870871
expr = self.parse_range_expr(expr)?;
871872
let next_precedence = self.get_next_precedence()?;
872873
debug!("next precedence: {:?}", next_precedence);
@@ -880,6 +881,30 @@ impl<'a> Parser<'a> {
880881
Ok(expr)
881882
}
882883

884+
/// Parse within syntax like `select * from monitor where ts within '2025-01'`
885+
fn parse_within_filter(&mut self, expr: Expr) -> Result<Expr, ParserError> {
886+
if !self.parse_keyword(Keyword::WITHIN) {
887+
return Ok(expr);
888+
}
889+
let Expr::Identifier(ident) = expr else {
890+
return Ok(expr);
891+
};
892+
let value = self.parse_value()?;
893+
Ok(Expr::Function(Function {
894+
name: ObjectName(vec![Ident::new("within_filter")]),
895+
args: vec![
896+
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier(ident))),
897+
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(value))),
898+
],
899+
filter: None,
900+
null_treatment: None,
901+
over: None,
902+
distinct: false,
903+
special: false,
904+
order_by: vec![],
905+
}))
906+
}
907+
883908
/// Parse Range clause with format `RANGE [ Duration literal | (INTERVAL [interval expr]) ] FILL [ NULL | PREV .....]`
884909
fn parse_range_expr(&mut self, expr: Expr) -> Result<Expr, ParserError> {
885910
let index = self.index;
@@ -10965,4 +10990,72 @@ mod tests {
1096510990

1096610991
assert!(Parser::parse_sql(&MySqlDialect {}, sql).is_err());
1096710992
}
10993+
10994+
#[test]
10995+
fn test_within_filter() {
10996+
let sql = "select * from monitors where ts within '2024';";
10997+
let mut parser = Parser::new(&GenericDialect {}).try_with_sql(sql).unwrap();
10998+
let result = parser.parse_query().unwrap();
10999+
if let SetExpr::Select(select) = result.body.as_ref() {
11000+
let expected = &select.selection;
11001+
assert_eq!(
11002+
expected,
11003+
&Some(Expr::Function(Function {
11004+
name: ObjectName(vec![Ident::new("within_filter")]),
11005+
args: vec![
11006+
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier(Ident::new(
11007+
"ts"
11008+
)))),
11009+
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
11010+
Value::SingleQuotedString("2024".to_string())
11011+
)))
11012+
],
11013+
filter: None,
11014+
null_treatment: None,
11015+
over: None,
11016+
distinct: false,
11017+
special: false,
11018+
order_by: vec![]
11019+
}))
11020+
);
11021+
} else {
11022+
unreachable!();
11023+
}
11024+
let sql = "select * from monitors where ts within '1915' and memory < 1024;";
11025+
let mut parser = Parser::new(&GenericDialect {}).try_with_sql(sql).unwrap();
11026+
let result = parser.parse_query().unwrap();
11027+
if let SetExpr::Select(select) = result.body.as_ref() {
11028+
let expected = &select.selection;
11029+
let within_expr = Expr::Function(Function {
11030+
name: ObjectName(vec![Ident::new("within_filter")]),
11031+
args: vec![
11032+
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier(Ident::new("ts")))),
11033+
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
11034+
Value::SingleQuotedString("1915".to_string()),
11035+
))),
11036+
],
11037+
filter: None,
11038+
null_treatment: None,
11039+
over: None,
11040+
distinct: false,
11041+
special: false,
11042+
order_by: vec![],
11043+
});
11044+
let right = Expr::BinaryOp {
11045+
left: Box::new(Expr::Identifier(Ident::new("memory"))),
11046+
op: BinaryOperator::Lt,
11047+
right: Box::new(Expr::Value(Value::Number("1024".to_string(), false))),
11048+
};
11049+
assert_eq!(
11050+
expected,
11051+
&Some(Expr::BinaryOp {
11052+
left: Box::new(within_expr),
11053+
op: BinaryOperator::And,
11054+
right: Box::new(right)
11055+
})
11056+
);
11057+
} else {
11058+
unreachable!();
11059+
}
11060+
}
1096811061
}

0 commit comments

Comments
 (0)