@@ -14064,93 +14064,70 @@ impl<'a> Parser<'a> {
1406414064 pub fn parse_cte(&mut self) -> Result<Cte, ParserError> {
1406514065 let name = self.parse_identifier()?;
1406614066
14067- let mut cte = if self.parse_keyword(Keyword::AS) {
14068- let mut is_materialized = None;
14069- if dialect_of!(self is PostgreSqlDialect) {
14070- if self.parse_keyword(Keyword::MATERIALIZED) {
14071- is_materialized = Some(CteAsMaterialized::Materialized);
14072- } else if self.parse_keywords(&[Keyword::NOT, Keyword::MATERIALIZED]) {
14073- is_materialized = Some(CteAsMaterialized::NotMaterialized);
14074- }
14075- }
14076- self.expect_token(&Token::LParen)?;
14077-
14078- let query = self.parse_query()?;
14079- let closing_paren_token = self.expect_token(&Token::RParen)?;
14080-
14081- let alias = TableAlias {
14082- explicit: false,
14083- name,
14084- columns: vec![],
14085- };
14086- Cte {
14087- alias,
14088- query,
14089- from: None,
14090- materialized: is_materialized,
14091- closing_paren_token: closing_paren_token.into(),
14092- }
14093- } else {
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 {
14067+ let as_optional = self.dialect.supports_cte_without_as();
14068+
14069+ // If AS is optional, first try to parse `name (query)` directly
14070+ if as_optional && !self.peek_keyword(Keyword::AS) {
14071+ if let Some((query, closing_paren_token)) = self.maybe_parse(|p| {
14072+ p.expect_token(&Token::LParen)?;
14073+ let query = p.parse_query()?;
14074+ let closing_paren_token = p.expect_token(&Token::RParen)?;
14075+ Ok((query, closing_paren_token))
14076+ })? {
14077+ let mut cte = Cte {
14078+ alias: TableAlias {
1410814079 explicit: false,
1410914080 name,
1411014081 columns: vec![],
14111- };
14112- Cte {
14113- alias ,
14114- query ,
14115- from: None ,
14116- materialized: None,
14117- closing_paren_token: closing_paren_token.into(),
14118- }
14082+ },
14083+ query,
14084+ from: None ,
14085+ materialized: None ,
14086+ closing_paren_token: closing_paren_token.into() ,
14087+ };
14088+ if self.parse_keyword(Keyword::FROM) {
14089+ cte.from = Some(self.parse_identifier()?);
1411914090 }
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)?;
14091+ return Ok(cte);
14092+ }
14093+ }
1413614094
14137- let query = self.parse_query()?;
14138- let closing_paren_token = self.expect_token(&Token::RParen)?;
14095+ // Determine column definitions and consume AS
14096+ let columns = if self.parse_keyword(Keyword::AS) {
14097+ vec![]
14098+ } else {
14099+ let columns = self.parse_table_alias_column_defs()?;
14100+ if as_optional {
14101+ let _ = self.parse_keyword(Keyword::AS);
14102+ } else {
14103+ self.expect_keyword_is(Keyword::AS)?;
14104+ }
14105+ columns
14106+ };
1413914107
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- }
14108+ let mut is_materialized = None;
14109+ if dialect_of!(self is PostgreSqlDialect) {
14110+ if self.parse_keyword(Keyword::MATERIALIZED) {
14111+ is_materialized = Some(CteAsMaterialized::Materialized);
14112+ } else if self.parse_keywords(&[Keyword::NOT, Keyword::MATERIALIZED]) {
14113+ is_materialized = Some(CteAsMaterialized::NotMaterialized);
1415314114 }
14115+ }
14116+
14117+ self.expect_token(&Token::LParen)?;
14118+ let query = self.parse_query()?;
14119+ let closing_paren_token = self.expect_token(&Token::RParen)?;
14120+
14121+ let mut cte = Cte {
14122+ alias: TableAlias {
14123+ explicit: false,
14124+ name,
14125+ columns,
14126+ },
14127+ query,
14128+ from: None,
14129+ materialized: is_materialized,
14130+ closing_paren_token: closing_paren_token.into(),
1415414131 };
1415514132 if self.parse_keyword(Keyword::FROM) {
1415614133 cte.from = Some(self.parse_identifier()?);
0 commit comments