Skip to content

Commit c4b7e7b

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

2 files changed

Lines changed: 26 additions & 16 deletions

File tree

src/parser/mod.rs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13562,7 +13562,7 @@ impl<'a> Parser<'a> {
1356213562
Keyword::PIVOT => {
1356313563
self.expect_token(&Token::LParen)?;
1356413564
let aggregate_functions =
13565-
self.parse_comma_separated(Self::parse_aliased_function_call)?;
13565+
self.parse_comma_separated(Self::parse_pivot_aggregate_function)?;
1356613566
self.expect_keyword_is(Keyword::FOR)?;
1356713567
let value_column = self.parse_period_separated(|p| p.parse_identifier())?;
1356813568
self.expect_keyword_is(Keyword::IN)?;
@@ -16153,20 +16153,6 @@ impl<'a> Parser<'a> {
1615316153
})
1615416154
}
1615516155

16156-
fn parse_aliased_function_call(&mut self) -> Result<ExprWithAlias, ParserError> {
16157-
let function_name = match self.next_token().token {
16158-
Token::Word(w) => Ok(w.value),
16159-
_ => self.expected("a function identifier", self.peek_token()),
16160-
}?;
16161-
let expr = self.parse_function(ObjectName::from(vec![Ident::new(function_name)]))?;
16162-
let alias = if self.parse_keyword(Keyword::AS) {
16163-
Some(self.parse_identifier()?)
16164-
} else {
16165-
None
16166-
};
16167-
16168-
Ok(ExprWithAlias { expr, alias })
16169-
}
1617016156
/// Parses an expression with an optional alias
1617116157
///
1617216158
/// Examples:
@@ -16209,13 +16195,31 @@ impl<'a> Parser<'a> {
1620916195
Ok(ExprWithAlias { expr, alias })
1621016196
}
1621116197

16198+
/// Parses a plain function call with an optional alias for the `PIVOT` clause
16199+
fn parse_pivot_aggregate_function(&mut self) -> Result<ExprWithAlias, ParserError> {
16200+
let function_name = match self.next_token().token {
16201+
Token::Word(w) => Ok(w.value),
16202+
_ => self.expected("a function identifier", self.peek_token()),
16203+
}?;
16204+
let expr = self.parse_function(ObjectName::from(vec![Ident::new(function_name)]))?;
16205+
let alias = {
16206+
fn validator(explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
16207+
// ~ for a PIVOT aggregate function the alias must not be a "FOR"; in any dialect
16208+
kw != &Keyword::FOR && parser.dialect.is_select_item_alias(explicit, kw, parser)
16209+
}
16210+
self.parse_optional_alias_inner(None, validator)?
16211+
};
16212+
Ok(ExprWithAlias { expr, alias })
16213+
}
16214+
1621216215
/// Parse a PIVOT table factor (ClickHouse/Oracle style pivot), returning a TableFactor.
1621316216
pub fn parse_pivot_table_factor(
1621416217
&mut self,
1621516218
table: TableFactor,
1621616219
) -> Result<TableFactor, ParserError> {
1621716220
self.expect_token(&Token::LParen)?;
16218-
let aggregate_functions = self.parse_comma_separated(Self::parse_aliased_function_call)?;
16221+
let aggregate_functions =
16222+
self.parse_comma_separated(Self::parse_pivot_aggregate_function)?;
1621916223
self.expect_keyword_is(Keyword::FOR)?;
1622016224
let value_column = if self.peek_token_ref().token == Token::LParen {
1622116225
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)