@@ -14060,7 +14060,7 @@ impl<'a> Parser<'a> {
1406014060 })
1406114061 }
1406214062
14063- /// Parse a CTE (`alias [( col1, col2, ... )] AS (subquery)`)
14063+ /// Parse a CTE (`alias [( col1, col2, ... )] [AS] (subquery)`)
1406414064 pub fn parse_cte(&mut self) -> Result<Cte, ParserError> {
1406514065 let name = self.parse_identifier()?;
1406614066
@@ -14091,32 +14091,65 @@ impl<'a> Parser<'a> {
1409114091 closing_paren_token: closing_paren_token.into(),
1409214092 }
1409314093 } else {
14094- let columns = self.parse_table_alias_column_defs()?;
14095- self.expect_keyword_is(Keyword::AS)?;
14096- let mut is_materialized = None;
14097- if dialect_of!(self is PostgreSqlDialect) {
14098- if self.parse_keyword(Keyword::MATERIALIZED) {
14099- is_materialized = Some(CteAsMaterialized::Materialized);
14100- } else if self.parse_keywords(&[Keyword::NOT, Keyword::MATERIALIZED]) {
14101- is_materialized = Some(CteAsMaterialized::NotMaterialized);
14094+ let as_optional = self.dialect.supports_cte_without_as();
14095+ let opt_query = if as_optional {
14096+ self.maybe_parse(|p| {
14097+ p.expect_token(&Token::LParen)?;
14098+ let query = p.parse_query()?;
14099+ let closing_paren_token = p.expect_token(&Token::RParen)?;
14100+ Ok((query, closing_paren_token))
14101+ })?
14102+ } else {
14103+ None
14104+ };
14105+ match opt_query {
14106+ Some((query, closing_paren_token)) => {
14107+ let alias = TableAlias {
14108+ explicit: false,
14109+ name,
14110+ columns: vec![],
14111+ };
14112+ Cte {
14113+ alias,
14114+ query,
14115+ from: None,
14116+ materialized: None,
14117+ closing_paren_token: closing_paren_token.into(),
14118+ }
1410214119 }
14103- }
14104- self.expect_token(&Token::LParen)?;
14120+ None => {
14121+ let columns = self.parse_table_alias_column_defs()?;
14122+ if as_optional {
14123+ let _ = self.parse_keyword(Keyword::AS);
14124+ } else {
14125+ self.expect_keyword_is(Keyword::AS)?;
14126+ }
14127+ let mut is_materialized = None;
14128+ if dialect_of!(self is PostgreSqlDialect) {
14129+ if self.parse_keyword(Keyword::MATERIALIZED) {
14130+ is_materialized = Some(CteAsMaterialized::Materialized);
14131+ } else if self.parse_keywords(&[Keyword::NOT, Keyword::MATERIALIZED]) {
14132+ is_materialized = Some(CteAsMaterialized::NotMaterialized);
14133+ }
14134+ }
14135+ self.expect_token(&Token::LParen)?;
1410514136
14106- let query = self.parse_query()?;
14107- let closing_paren_token = self.expect_token(&Token::RParen)?;
14137+ let query = self.parse_query()?;
14138+ let closing_paren_token = self.expect_token(&Token::RParen)?;
1410814139
14109- let alias = TableAlias {
14110- explicit: false,
14111- name,
14112- columns,
14113- };
14114- Cte {
14115- alias,
14116- query,
14117- from: None,
14118- materialized: is_materialized,
14119- closing_paren_token: closing_paren_token.into(),
14140+ let alias = TableAlias {
14141+ explicit: false,
14142+ name,
14143+ columns,
14144+ };
14145+ Cte {
14146+ alias,
14147+ query,
14148+ from: None,
14149+ materialized: is_materialized,
14150+ closing_paren_token: closing_paren_token.into(),
14151+ }
14152+ }
1412014153 }
1412114154 };
1412214155 if self.parse_keyword(Keyword::FROM) {
0 commit comments