Skip to content

Commit e2c569d

Browse files
committed
[PIVOT] Optional AS keyword for aggregation function aliases
1 parent b6359c1 commit e2c569d

File tree

2 files changed

+26
-16
lines changed

2 files changed

+26
-16
lines changed

src/parser/mod.rs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13543,7 +13543,7 @@ impl<'a> Parser<'a> {
1354313543
Keyword::PIVOT => {
1354413544
self.expect_token(&Token::LParen)?;
1354513545
let aggregate_functions =
13546-
self.parse_comma_separated(Self::parse_aliased_function_call)?;
13546+
self.parse_comma_separated(Self::parse_pivot_aggregate_function)?;
1354713547
self.expect_keyword_is(Keyword::FOR)?;
1354813548
let value_column = self.parse_period_separated(|p| p.parse_identifier())?;
1354913549
self.expect_keyword_is(Keyword::IN)?;
@@ -16125,20 +16125,6 @@ impl<'a> Parser<'a> {
1612516125
})
1612616126
}
1612716127

16128-
fn parse_aliased_function_call(&mut self) -> Result<ExprWithAlias, ParserError> {
16129-
let function_name = match self.next_token().token {
16130-
Token::Word(w) => Ok(w.value),
16131-
_ => self.expected("a function identifier", self.peek_token()),
16132-
}?;
16133-
let expr = self.parse_function(ObjectName::from(vec![Ident::new(function_name)]))?;
16134-
let alias = if self.parse_keyword(Keyword::AS) {
16135-
Some(self.parse_identifier()?)
16136-
} else {
16137-
None
16138-
};
16139-
16140-
Ok(ExprWithAlias { expr, alias })
16141-
}
1614216128
/// Parses an expression with an optional alias
1614316129
///
1614416130
/// Examples:
@@ -16181,13 +16167,31 @@ impl<'a> Parser<'a> {
1618116167
Ok(ExprWithAlias { expr, alias })
1618216168
}
1618316169

16170+
/// Parses a plain function call with an optional alias for the `PIVOT` clause
16171+
fn parse_pivot_aggregate_function(&mut self) -> Result<ExprWithAlias, ParserError> {
16172+
let function_name = match self.next_token().token {
16173+
Token::Word(w) => Ok(w.value),
16174+
_ => self.expected("a function identifier", self.peek_token()),
16175+
}?;
16176+
let expr = self.parse_function(ObjectName::from(vec![Ident::new(function_name)]))?;
16177+
let alias = {
16178+
fn validator(explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
16179+
// ~ for a PIVOT aggregate function the alias must not be a "FOR"; in any dialect
16180+
kw != &Keyword::FOR && parser.dialect.is_select_item_alias(explicit, kw, parser)
16181+
}
16182+
self.parse_optional_alias_inner(None, validator)?
16183+
};
16184+
Ok(ExprWithAlias { expr, alias })
16185+
}
16186+
1618416187
/// Parse a PIVOT table factor (ClickHouse/Oracle style pivot), returning a TableFactor.
1618516188
pub fn parse_pivot_table_factor(
1618616189
&mut self,
1618716190
table: TableFactor,
1618816191
) -> Result<TableFactor, ParserError> {
1618916192
self.expect_token(&Token::LParen)?;
16190-
let aggregate_functions = self.parse_comma_separated(Self::parse_aliased_function_call)?;
16193+
let aggregate_functions =
16194+
self.parse_comma_separated(Self::parse_pivot_aggregate_function)?;
1619116195
self.expect_keyword_is(Keyword::FOR)?;
1619216196
let value_column = if self.peek_token_ref().token == Token::LParen {
1619316197
self.parse_parenthesized_column_list_inner(Mandatory, false, |p| {

tests/sqlparser_common.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11363,6 +11363,12 @@ fn parse_pivot_table() {
1136311363
"SELECT * FROM t PIVOT(SUM(1) FOR a.abc IN (1 x, 'two' y, three z))",
1136411364
"SELECT * FROM t PIVOT(SUM(1) FOR a.abc IN (1 AS x, 'two' AS y, three AS z))",
1136511365
);
11366+
11367+
// assert optional "AS" keyword for aliases for pivot aggregate function
11368+
one_statement_parses_to(
11369+
"SELECT * FROM t PIVOT(SUM(1) x, COUNT(42) y FOR a.abc IN (1))",
11370+
"SELECT * FROM t PIVOT(SUM(1) AS x, COUNT(42) AS y FOR a.abc IN (1))",
11371+
);
1136611372
}
1136711373

1136811374
#[test]

0 commit comments

Comments
 (0)