@@ -16584,6 +16584,12 @@ impl<'a> Parser<'a> {
1658416584 // `(mytable AS alias)`
1658516585 alias.replace(outer_alias);
1658616586 }
16587+ TableFactor::UnpivotExpr { .. } => {
16588+ return Err(ParserError::ParserError(
16589+ "alias after parenthesized UNPIVOT expression is not supported"
16590+ .to_string(),
16591+ ))
16592+ }
1658716593 };
1658816594 }
1658916595 // Do not store the extra set of parens in the AST
@@ -16665,6 +16671,8 @@ impl<'a> Parser<'a> {
1666516671 with_offset_alias,
1666616672 with_ordinality,
1666716673 })
16674+ } else if self.dialect.supports_unpivot_expr() && self.peek_keyword(Keyword::UNPIVOT) {
16675+ self.parse_unpivot_expr_table_factor()
1666816676 } else if self.parse_keyword_with_tokens(Keyword::JSON_TABLE, &[Token::LParen]) {
1666916677 let json_expr = self.parse_expr()?;
1667016678 self.expect_token(&Token::Comma)?;
@@ -17663,6 +17671,28 @@ impl<'a> Parser<'a> {
1766317671 })
1766417672 }
1766517673
17674+ /// Parse an object UNPIVOT table factor in FROM clause.
17675+ ///
17676+ /// Syntax:
17677+ /// `UNPIVOT expression AS value_alias [AT attribute_alias]`
17678+ pub fn parse_unpivot_expr_table_factor(&mut self) -> Result<TableFactor, ParserError> {
17679+ self.expect_keyword_is(Keyword::UNPIVOT)?;
17680+ let expression = self.parse_expr()?;
17681+ self.expect_keyword_is(Keyword::AS)?;
17682+ let value_alias = self.parse_identifier()?;
17683+ let attribute_alias = if self.parse_keyword(Keyword::AT) {
17684+ Some(self.parse_identifier()?)
17685+ } else {
17686+ None
17687+ };
17688+
17689+ Ok(TableFactor::UnpivotExpr {
17690+ expression,
17691+ value_alias,
17692+ attribute_alias,
17693+ })
17694+ }
17695+
1766617696 /// Parse a JOIN constraint (`NATURAL`, `ON <expr>`, `USING (...)`, or no constraint).
1766717697 pub fn parse_join_constraint(&mut self, natural: bool) -> Result<JoinConstraint, ParserError> {
1766817698 if natural {
0 commit comments