Skip to content

Commit 1b86abe

Browse files
authored
Add support for first, last aggregate function parsing (#882)
* Add order by parsing to functions * Fix doc error * minor changes
1 parent 33b12ac commit 1b86abe

12 files changed

+96
-7
lines changed

src/ast/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3366,6 +3366,8 @@ pub struct Function {
33663366
// Some functions must be called without trailing parentheses, for example Postgres
33673367
// do it for current_catalog, current_schema, etc. This flags is used for formatting.
33683368
pub special: bool,
3369+
// Required ordering for the function (if empty, there is no requirement).
3370+
pub order_by: Vec<OrderByExpr>,
33693371
}
33703372

33713373
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
@@ -3392,12 +3394,18 @@ impl fmt::Display for Function {
33923394
if self.special {
33933395
write!(f, "{}", self.name)?;
33943396
} else {
3397+
let order_by = if !self.order_by.is_empty() {
3398+
" ORDER BY "
3399+
} else {
3400+
""
3401+
};
33953402
write!(
33963403
f,
3397-
"{}({}{})",
3404+
"{}({}{}{order_by}{})",
33983405
self.name,
33993406
if self.distinct { "DISTINCT " } else { "" },
34003407
display_comma_separated(&self.args),
3408+
display_comma_separated(&self.order_by),
34013409
)?;
34023410

34033411
if let Some(o) = &self.over {

src/ast/visitor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ where
480480
/// *expr = Expr::Function(Function {
481481
/// name: ObjectName(vec![Ident::new("f")]),
482482
/// args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(old_expr))],
483-
/// over: None, distinct: false, special: false,
483+
/// over: None, distinct: false, special: false, order_by: vec![],
484484
/// });
485485
/// }
486486
/// ControlFlow::<()>::Continue(())

src/parser.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,7 @@ impl<'a> Parser<'a> {
706706
over: None,
707707
distinct: false,
708708
special: true,
709+
order_by: vec![],
709710
}))
710711
}
711712
Keyword::CURRENT_TIMESTAMP
@@ -881,7 +882,7 @@ impl<'a> Parser<'a> {
881882
pub fn parse_function(&mut self, name: ObjectName) -> Result<Expr, ParserError> {
882883
self.expect_token(&Token::LParen)?;
883884
let distinct = self.parse_all_or_distinct()?.is_some();
884-
let args = self.parse_optional_args()?;
885+
let (args, order_by) = self.parse_optional_args_with_orderby()?;
885886
let over = if self.parse_keyword(Keyword::OVER) {
886887
// TBD: support window names (`OVER mywin`) in place of inline specification
887888
self.expect_token(&Token::LParen)?;
@@ -918,21 +919,23 @@ impl<'a> Parser<'a> {
918919
over,
919920
distinct,
920921
special: false,
922+
order_by,
921923
}))
922924
}
923925

924926
pub fn parse_time_functions(&mut self, name: ObjectName) -> Result<Expr, ParserError> {
925-
let args = if self.consume_token(&Token::LParen) {
926-
self.parse_optional_args()?
927+
let (args, order_by) = if self.consume_token(&Token::LParen) {
928+
self.parse_optional_args_with_orderby()?
927929
} else {
928-
vec![]
930+
(vec![], vec![])
929931
};
930932
Ok(Expr::Function(Function {
931933
name,
932934
args,
933935
over: None,
934936
distinct: false,
935937
special: false,
938+
order_by,
936939
}))
937940
}
938941

@@ -6376,6 +6379,23 @@ impl<'a> Parser<'a> {
63766379
}
63776380
}
63786381

6382+
pub fn parse_optional_args_with_orderby(
6383+
&mut self,
6384+
) -> Result<(Vec<FunctionArg>, Vec<OrderByExpr>), ParserError> {
6385+
if self.consume_token(&Token::RParen) {
6386+
Ok((vec![], vec![]))
6387+
} else {
6388+
let args = self.parse_comma_separated(Parser::parse_function_args)?;
6389+
let order_by = if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
6390+
self.parse_comma_separated(Parser::parse_order_by_expr)?
6391+
} else {
6392+
vec![]
6393+
};
6394+
self.expect_token(&Token::RParen)?;
6395+
Ok((args, order_by))
6396+
}
6397+
}
6398+
63796399
/// Parse a comma-delimited list of projections after SELECT
63806400
pub fn parse_select_item(&mut self) -> Result<SelectItem, ParserError> {
63816401
match self.parse_wildcard_expr()? {

tests/sqlparser_bigquery.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,7 @@ fn parse_map_access_offset() {
437437
over: None,
438438
distinct: false,
439439
special: false,
440+
order_by: vec![],
440441
})],
441442
})
442443
);

tests/sqlparser_clickhouse.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ fn parse_map_access_expr() {
5252
over: None,
5353
distinct: false,
5454
special: false,
55+
order_by: vec![],
5556
})],
5657
})],
5758
into: None,
@@ -88,6 +89,7 @@ fn parse_map_access_expr() {
8889
over: None,
8990
distinct: false,
9091
special: false,
92+
order_by: vec![],
9193
})]
9294
}),
9395
op: BinaryOperator::NotEq,
@@ -135,6 +137,7 @@ fn parse_array_fn() {
135137
over: None,
136138
distinct: false,
137139
special: false,
140+
order_by: vec![],
138141
}),
139142
expr_from_projection(only(&select.projection))
140143
);
@@ -189,6 +192,7 @@ fn parse_delimited_identifiers() {
189192
over: None,
190193
distinct: false,
191194
special: false,
195+
order_by: vec![],
192196
}),
193197
expr_from_projection(&select.projection[1]),
194198
);

tests/sqlparser_common.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,7 @@ fn parse_select_count_wildcard() {
840840
over: None,
841841
distinct: false,
842842
special: false,
843+
order_by: vec![],
843844
}),
844845
expr_from_projection(only(&select.projection))
845846
);
@@ -859,6 +860,7 @@ fn parse_select_count_distinct() {
859860
over: None,
860861
distinct: true,
861862
special: false,
863+
order_by: vec![],
862864
}),
863865
expr_from_projection(only(&select.projection))
864866
);
@@ -1696,6 +1698,7 @@ fn parse_select_having() {
16961698
over: None,
16971699
distinct: false,
16981700
special: false,
1701+
order_by: vec![],
16991702
})),
17001703
op: BinaryOperator::Gt,
17011704
right: Box::new(Expr::Value(number("1"))),
@@ -1729,6 +1732,7 @@ fn parse_select_qualify() {
17291732
}),
17301733
distinct: false,
17311734
special: false,
1735+
order_by: vec![],
17321736
})),
17331737
op: BinaryOperator::Eq,
17341738
right: Box::new(Expr::Value(number("1"))),
@@ -2076,6 +2080,29 @@ fn parse_array_agg_func() {
20762080
}
20772081
}
20782082

2083+
#[test]
2084+
fn parse_agg_with_order_by() {
2085+
let supported_dialects = TestedDialects {
2086+
dialects: vec![
2087+
Box::new(GenericDialect {}),
2088+
Box::new(PostgreSqlDialect {}),
2089+
Box::new(MsSqlDialect {}),
2090+
Box::new(AnsiDialect {}),
2091+
Box::new(HiveDialect {}),
2092+
],
2093+
options: None,
2094+
};
2095+
2096+
for sql in [
2097+
"SELECT FIRST_VALUE(x ORDER BY x) AS a FROM T",
2098+
"SELECT FIRST_VALUE(x ORDER BY x) FROM tbl",
2099+
"SELECT LAST_VALUE(x ORDER BY x, y) AS a FROM T",
2100+
"SELECT LAST_VALUE(x ORDER BY x ASC, y DESC) AS a FROM T",
2101+
] {
2102+
supported_dialects.verified_stmt(sql);
2103+
}
2104+
}
2105+
20792106
#[test]
20802107
fn parse_create_table() {
20812108
let sql = "CREATE TABLE uk_cities (\
@@ -3121,6 +3148,7 @@ fn parse_scalar_function_in_projection() {
31213148
over: None,
31223149
distinct: false,
31233150
special: false,
3151+
order_by: vec![],
31243152
}),
31253153
expr_from_projection(only(&select.projection))
31263154
);
@@ -3239,6 +3267,7 @@ fn parse_named_argument_function() {
32393267
over: None,
32403268
distinct: false,
32413269
special: false,
3270+
order_by: vec![],
32423271
}),
32433272
expr_from_projection(only(&select.projection))
32443273
);
@@ -3277,6 +3306,7 @@ fn parse_window_functions() {
32773306
}),
32783307
distinct: false,
32793308
special: false,
3309+
order_by: vec![],
32803310
}),
32813311
expr_from_projection(&select.projection[0])
32823312
);
@@ -3675,6 +3705,7 @@ fn parse_at_timezone() {
36753705
over: None,
36763706
distinct: false,
36773707
special: false,
3708+
order_by: vec![],
36783709
})),
36793710
time_zone: "UTC-06:00".to_string(),
36803711
},
@@ -3701,6 +3732,7 @@ fn parse_at_timezone() {
37013732
over: None,
37023733
distinct: false,
37033734
special: false,
3735+
order_by: vec![],
37043736
},)),
37053737
time_zone: "UTC-06:00".to_string(),
37063738
},),),
@@ -3711,6 +3743,7 @@ fn parse_at_timezone() {
37113743
over: None,
37123744
distinct: false,
37133745
special: false,
3746+
order_by: vec![],
37143747
},),
37153748
alias: Ident {
37163749
value: "hour".to_string(),
@@ -3868,6 +3901,7 @@ fn parse_table_function() {
38683901
over: None,
38693902
distinct: false,
38703903
special: false,
3904+
order_by: vec![],
38713905
});
38723906
assert_eq!(expr, expected_expr);
38733907
assert_eq!(alias, table_alias("a"))
@@ -6292,6 +6326,7 @@ fn parse_time_functions() {
62926326
over: None,
62936327
distinct: false,
62946328
special: false,
6329+
order_by: vec![],
62956330
}),
62966331
expr_from_projection(&select.projection[0])
62976332
);
@@ -6308,6 +6343,7 @@ fn parse_time_functions() {
63086343
over: None,
63096344
distinct: false,
63106345
special: false,
6346+
order_by: vec![],
63116347
}),
63126348
expr_from_projection(&select.projection[0])
63136349
);
@@ -6324,6 +6360,7 @@ fn parse_time_functions() {
63246360
over: None,
63256361
distinct: false,
63266362
special: false,
6363+
order_by: vec![],
63276364
}),
63286365
expr_from_projection(&select.projection[0])
63296366
);
@@ -6340,6 +6377,7 @@ fn parse_time_functions() {
63406377
over: None,
63416378
distinct: false,
63426379
special: false,
6380+
order_by: vec![],
63436381
}),
63446382
expr_from_projection(&select.projection[0])
63456383
);
@@ -6356,6 +6394,7 @@ fn parse_time_functions() {
63566394
over: None,
63576395
distinct: false,
63586396
special: false,
6397+
order_by: vec![],
63596398
}),
63606399
expr_from_projection(&select.projection[0])
63616400
);
@@ -6820,6 +6859,7 @@ fn parse_pivot_table() {
68206859
over: None,
68216860
distinct: false,
68226861
special: false,
6862+
order_by: vec![],
68236863
}),
68246864
value_column: vec![Ident::new("a"), Ident::new("MONTH")],
68256865
pivot_values: vec![

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
over: None,
347347
distinct: false,
348348
special: false,
349+
order_by: vec![],
349350
}),
350351
expr_from_projection(&select.projection[1]),
351352
);

tests/sqlparser_mssql.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ fn parse_delimited_identifiers() {
177177
over: None,
178178
distinct: false,
179179
special: false,
180+
order_by: vec![],
180181
}),
181182
expr_from_projection(&select.projection[1]),
182183
);

tests/sqlparser_mysql.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,7 @@ fn parse_insert_with_on_duplicate_update() {
791791
over: None,
792792
distinct: false,
793793
special: false,
794+
order_by: vec![],
794795
})
795796
},
796797
Assignment {
@@ -803,6 +804,7 @@ fn parse_insert_with_on_duplicate_update() {
803804
over: None,
804805
distinct: false,
805806
special: false,
807+
order_by: vec![],
806808
})
807809
},
808810
Assignment {
@@ -815,6 +817,7 @@ fn parse_insert_with_on_duplicate_update() {
815817
over: None,
816818
distinct: false,
817819
special: false,
820+
order_by: vec![],
818821
})
819822
},
820823
Assignment {
@@ -827,6 +830,7 @@ fn parse_insert_with_on_duplicate_update() {
827830
over: None,
828831
distinct: false,
829832
special: false,
833+
order_by: vec![],
830834
})
831835
},
832836
Assignment {
@@ -839,6 +843,7 @@ fn parse_insert_with_on_duplicate_update() {
839843
over: None,
840844
distinct: false,
841845
special: false,
846+
order_by: vec![],
842847
})
843848
},
844849
])),
@@ -1182,6 +1187,7 @@ fn parse_table_colum_option_on_update() {
11821187
over: None,
11831188
distinct: false,
11841189
special: false,
1190+
order_by: vec![],
11851191
})),
11861192
},],
11871193
}],

0 commit comments

Comments
 (0)