Skip to content

Commit ce62fe6

Browse files
lovasoaalamb
andauthored
Support FILTER in over clause (apache#1007)
Co-authored-by: Andrew Lamb <[email protected]>
1 parent e857a45 commit ce62fe6

15 files changed

+102
-2
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ println!("AST: {:?}", ast);
3434
This outputs
3535

3636
```rust
37-
AST: [Query(Query { ctes: [], body: Select(Select { distinct: false, projection: [UnnamedExpr(Identifier("a")), UnnamedExpr(Identifier("b")), UnnamedExpr(Value(Long(123))), UnnamedExpr(Function(Function { name: ObjectName(["myfunc"]), args: [Identifier("b")], over: None, distinct: false }))], from: [TableWithJoins { relation: Table { name: ObjectName(["table_1"]), alias: None, args: [], with_hints: [] }, joins: [] }], selection: Some(BinaryOp { left: BinaryOp { left: Identifier("a"), op: Gt, right: Identifier("b") }, op: And, right: BinaryOp { left: Identifier("b"), op: Lt, right: Value(Long(100)) } }), group_by: [], having: None }), order_by: [OrderByExpr { expr: Identifier("a"), asc: Some(false) }, OrderByExpr { expr: Identifier("b"), asc: None }], limit: None, offset: None, fetch: None })]
37+
AST: [Query(Query { ctes: [], body: Select(Select { distinct: false, projection: [UnnamedExpr(Identifier("a")), UnnamedExpr(Identifier("b")), UnnamedExpr(Value(Long(123))), UnnamedExpr(Function(Function { name: ObjectName(["myfunc"]), args: [Identifier("b")], filter: None, over: None, distinct: false }))], from: [TableWithJoins { relation: Table { name: ObjectName(["table_1"]), alias: None, args: [], with_hints: [] }, joins: [] }], selection: Some(BinaryOp { left: BinaryOp { left: Identifier("a"), op: Gt, right: Identifier("b") }, op: And, right: BinaryOp { left: Identifier("b"), op: Lt, right: Value(Long(100)) } }), group_by: [], having: None }), order_by: [OrderByExpr { expr: Identifier("a"), asc: Some(false) }, OrderByExpr { expr: Identifier("b"), asc: None }], limit: None, offset: None, fetch: None })]
3838
```
3939

4040

src/ast/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,8 +1070,11 @@ impl Display for WindowType {
10701070
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10711071
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10721072
pub struct WindowSpec {
1073+
/// `OVER (PARTITION BY ...)`
10731074
pub partition_by: Vec<Expr>,
1075+
/// `OVER (ORDER BY ...)`
10741076
pub order_by: Vec<OrderByExpr>,
1077+
/// `OVER (window frame)`
10751078
pub window_frame: Option<WindowFrame>,
10761079
}
10771080

@@ -3729,6 +3732,8 @@ impl fmt::Display for CloseCursor {
37293732
pub struct Function {
37303733
pub name: ObjectName,
37313734
pub args: Vec<FunctionArg>,
3735+
/// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
3736+
pub filter: Option<Box<Expr>>,
37323737
pub over: Option<WindowType>,
37333738
// aggregate functions may specify eg `COUNT(DISTINCT x)`
37343739
pub distinct: bool,
@@ -3777,6 +3782,10 @@ impl fmt::Display for Function {
37773782
display_comma_separated(&self.order_by),
37783783
)?;
37793784

3785+
if let Some(filter_cond) = &self.filter {
3786+
write!(f, " FILTER (WHERE {filter_cond})")?;
3787+
}
3788+
37803789
if let Some(o) = &self.over {
37813790
write!(f, " OVER {o}")?;
37823791
}

src/ast/visitor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ where
506506
/// *expr = Expr::Function(Function {
507507
/// name: ObjectName(vec![Ident::new("f")]),
508508
/// args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(old_expr))],
509-
/// over: None, distinct: false, special: false, order_by: vec![],
509+
/// filter: None, over: None, distinct: false, special: false, order_by: vec![],
510510
/// });
511511
/// }
512512
/// ControlFlow::<()>::Continue(())

src/dialect/sqlite.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ impl Dialect for SQLiteDialect {
3535
|| ('\u{007f}'..='\u{ffff}').contains(&ch)
3636
}
3737

38+
fn supports_filter_during_aggregation(&self) -> bool {
39+
true
40+
}
41+
3842
fn is_identifier_part(&self, ch: char) -> bool {
3943
self.is_identifier_start(ch) || ch.is_ascii_digit()
4044
}

src/parser/mod.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,7 @@ impl<'a> Parser<'a> {
772772
Ok(Expr::Function(Function {
773773
name: ObjectName(vec![w.to_ident()]),
774774
args: vec![],
775+
filter: None,
775776
over: None,
776777
distinct: false,
777778
special: true,
@@ -957,6 +958,17 @@ impl<'a> Parser<'a> {
957958
self.expect_token(&Token::LParen)?;
958959
let distinct = self.parse_all_or_distinct()?.is_some();
959960
let (args, order_by) = self.parse_optional_args_with_orderby()?;
961+
let filter = if self.dialect.supports_filter_during_aggregation()
962+
&& self.parse_keyword(Keyword::FILTER)
963+
&& self.consume_token(&Token::LParen)
964+
&& self.parse_keyword(Keyword::WHERE)
965+
{
966+
let filter = Some(Box::new(self.parse_expr()?));
967+
self.expect_token(&Token::RParen)?;
968+
filter
969+
} else {
970+
None
971+
};
960972
let over = if self.parse_keyword(Keyword::OVER) {
961973
if self.consume_token(&Token::LParen) {
962974
let window_spec = self.parse_window_spec()?;
@@ -970,6 +982,7 @@ impl<'a> Parser<'a> {
970982
Ok(Expr::Function(Function {
971983
name,
972984
args,
985+
filter,
973986
over,
974987
distinct,
975988
special: false,
@@ -987,6 +1000,7 @@ impl<'a> Parser<'a> {
9871000
Ok(Expr::Function(Function {
9881001
name,
9891002
args,
1003+
filter: None,
9901004
over: None,
9911005
distinct: false,
9921006
special,

tests/sqlparser_bigquery.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,7 @@ fn parse_map_access_offset() {
564564
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
565565
number("0")
566566
))),],
567+
filter: None,
567568
over: None,
568569
distinct: false,
569570
special: false,

tests/sqlparser_clickhouse.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ fn parse_map_access_expr() {
5050
Value::SingleQuotedString("endpoint".to_string())
5151
))),
5252
],
53+
filter: None,
5354
over: None,
5455
distinct: false,
5556
special: false,
@@ -89,6 +90,7 @@ fn parse_map_access_expr() {
8990
Value::SingleQuotedString("app".to_string())
9091
))),
9192
],
93+
filter: None,
9294
over: None,
9395
distinct: false,
9496
special: false,
@@ -138,6 +140,7 @@ fn parse_array_fn() {
138140
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier(Ident::new("x1")))),
139141
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier(Ident::new("x2")))),
140142
],
143+
filter: None,
141144
over: None,
142145
distinct: false,
143146
special: false,
@@ -196,6 +199,7 @@ fn parse_delimited_identifiers() {
196199
&Expr::Function(Function {
197200
name: ObjectName(vec![Ident::with_quote('"', "myfun")]),
198201
args: vec![],
202+
filter: None,
199203
over: None,
200204
distinct: false,
201205
special: false,

tests/sqlparser_common.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,7 @@ fn parse_select_count_wildcard() {
875875
&Expr::Function(Function {
876876
name: ObjectName(vec![Ident::new("COUNT")]),
877877
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Wildcard)],
878+
filter: None,
878879
over: None,
879880
distinct: false,
880881
special: false,
@@ -895,6 +896,7 @@ fn parse_select_count_distinct() {
895896
op: UnaryOperator::Plus,
896897
expr: Box::new(Expr::Identifier(Ident::new("x"))),
897898
}))],
899+
filter: None,
898900
over: None,
899901
distinct: true,
900902
special: false,
@@ -1862,6 +1864,7 @@ fn parse_select_having() {
18621864
left: Box::new(Expr::Function(Function {
18631865
name: ObjectName(vec![Ident::new("COUNT")]),
18641866
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Wildcard)],
1867+
filter: None,
18651868
over: None,
18661869
distinct: false,
18671870
special: false,
@@ -1887,6 +1890,7 @@ fn parse_select_qualify() {
18871890
left: Box::new(Expr::Function(Function {
18881891
name: ObjectName(vec![Ident::new("ROW_NUMBER")]),
18891892
args: vec![],
1893+
filter: None,
18901894
over: Some(WindowType::WindowSpec(WindowSpec {
18911895
partition_by: vec![Expr::Identifier(Ident::new("p"))],
18921896
order_by: vec![OrderByExpr {
@@ -3342,6 +3346,7 @@ fn parse_scalar_function_in_projection() {
33423346
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
33433347
Expr::Identifier(Ident::new("id"))
33443348
))],
3349+
filter: None,
33453350
over: None,
33463351
distinct: false,
33473352
special: false,
@@ -3461,6 +3466,7 @@ fn parse_named_argument_function() {
34613466
))),
34623467
},
34633468
],
3469+
filter: None,
34643470
over: None,
34653471
distinct: false,
34663472
special: false,
@@ -3492,6 +3498,7 @@ fn parse_window_functions() {
34923498
&Expr::Function(Function {
34933499
name: ObjectName(vec![Ident::new("row_number")]),
34943500
args: vec![],
3501+
filter: None,
34953502
over: Some(WindowType::WindowSpec(WindowSpec {
34963503
partition_by: vec![],
34973504
order_by: vec![OrderByExpr {
@@ -3535,6 +3542,7 @@ fn test_parse_named_window() {
35353542
quote_style: None,
35363543
}),
35373544
))],
3545+
filter: None,
35383546
over: Some(WindowType::NamedWindow(Ident {
35393547
value: "window1".to_string(),
35403548
quote_style: None,
@@ -3560,6 +3568,7 @@ fn test_parse_named_window() {
35603568
quote_style: None,
35613569
}),
35623570
))],
3571+
filter: None,
35633572
over: Some(WindowType::NamedWindow(Ident {
35643573
value: "window2".to_string(),
35653574
quote_style: None,
@@ -4029,6 +4038,7 @@ fn parse_at_timezone() {
40294038
quote_style: None,
40304039
}]),
40314040
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(zero.clone()))],
4041+
filter: None,
40324042
over: None,
40334043
distinct: false,
40344044
special: false,
@@ -4056,6 +4066,7 @@ fn parse_at_timezone() {
40564066
quote_style: None,
40574067
},],),
40584068
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(zero))],
4069+
filter: None,
40594070
over: None,
40604071
distinct: false,
40614072
special: false,
@@ -4067,6 +4078,7 @@ fn parse_at_timezone() {
40674078
Value::SingleQuotedString("%Y-%m-%dT%H".to_string()),
40684079
),),),
40694080
],
4081+
filter: None,
40704082
over: None,
40714083
distinct: false,
40724084
special: false,
@@ -4225,6 +4237,7 @@ fn parse_table_function() {
42254237
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
42264238
Value::SingleQuotedString("1".to_owned()),
42274239
)))],
4240+
filter: None,
42284241
over: None,
42294242
distinct: false,
42304243
special: false,
@@ -4376,6 +4389,7 @@ fn parse_unnest_in_from_clause() {
43764389
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("2")))),
43774390
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("3")))),
43784391
],
4392+
filter: None,
43794393
over: None,
43804394
distinct: false,
43814395
special: false,
@@ -4405,6 +4419,7 @@ fn parse_unnest_in_from_clause() {
44054419
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("2")))),
44064420
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("3")))),
44074421
],
4422+
filter: None,
44084423
over: None,
44094424
distinct: false,
44104425
special: false,
@@ -4416,6 +4431,7 @@ fn parse_unnest_in_from_clause() {
44164431
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("5")))),
44174432
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("6")))),
44184433
],
4434+
filter: None,
44194435
over: None,
44204436
distinct: false,
44214437
special: false,
@@ -6888,6 +6904,7 @@ fn parse_time_functions() {
68886904
let select_localtime_func_call_ast = Function {
68896905
name: ObjectName(vec![Ident::new(func_name)]),
68906906
args: vec![],
6907+
filter: None,
68916908
over: None,
68926909
distinct: false,
68936910
special: false,
@@ -7374,6 +7391,7 @@ fn parse_pivot_table() {
73747391
args: (vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
73757392
Expr::CompoundIdentifier(vec![Ident::new("a"), Ident::new("amount"),])
73767393
))]),
7394+
filter: None,
73777395
over: None,
73787396
distinct: false,
73797397
special: false,
@@ -7523,6 +7541,7 @@ fn parse_pivot_unpivot_table() {
75237541
args: (vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
75247542
Expr::Identifier(Ident::new("population"))
75257543
))]),
7544+
filter: None,
75267545
over: None,
75277546
distinct: false,
75287547
special: false,

tests/sqlparser_hive.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ fn parse_delimited_identifiers() {
346346
&Expr::Function(Function {
347347
name: ObjectName(vec![Ident::with_quote('"', "myfun")]),
348348
args: vec![],
349+
filter: None,
349350
over: None,
350351
distinct: false,
351352
special: false,

tests/sqlparser_mssql.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ fn parse_delimited_identifiers() {
334334
&Expr::Function(Function {
335335
name: ObjectName(vec![Ident::with_quote('"', "myfun")]),
336336
args: vec![],
337+
filter: None,
337338
over: None,
338339
distinct: false,
339340
special: false,

0 commit comments

Comments
 (0)