@@ -2158,14 +2158,58 @@ impl<'a> Parser<'a> {
21582158 // recently consumed does not start a derived table (cases 1, 2, or 4).
21592159 // `maybe_parse` will ignore such an error and rewind to be after the opening '('.
21602160
2161- // Inside the parentheses we expect to find a table factor
2162- // followed by some joins or another level of nesting.
2163- let table_and_joins = self . parse_table_and_joins ( ) ?;
2164- self . expect_token ( & Token :: RParen ) ?;
2165- // The SQL spec prohibits derived and bare tables from appearing
2166- // alone in parentheses. We don't enforce this as some databases
2167- // (e.g. Snowflake) allow such syntax.
2168- Ok ( TableFactor :: NestedJoin ( Box :: new ( table_and_joins) ) )
2161+ // Inside the parentheses we expect to find an (A) table factor
2162+ // followed by some joins or (B) another level of nesting.
2163+ let mut table_and_joins = self . parse_table_and_joins ( ) ?;
2164+
2165+ if !table_and_joins. joins . is_empty ( ) {
2166+ self . expect_token ( & Token :: RParen ) ?;
2167+ Ok ( TableFactor :: NestedJoin ( Box :: new ( table_and_joins) ) ) // (A)
2168+ } else if let TableFactor :: NestedJoin ( _) = & table_and_joins. relation {
2169+ // (B): `table_and_joins` (what we found inside the parentheses)
2170+ // is a nested join `(foo JOIN bar)`, not followed by other joins.
2171+ self . expect_token ( & Token :: RParen ) ?;
2172+ Ok ( TableFactor :: NestedJoin ( Box :: new ( table_and_joins) ) )
2173+ } else if dialect_of ! ( self is SnowflakeDialect | GenericDialect ) {
2174+ // Dialect-specific behavior: Snowflake diverges from the
2175+ // standard and from most of the other implementations by
2176+ // allowing extra parentheses not only around a join (B), but
2177+ // around lone table names (e.g. `FROM (mytable [AS alias])`)
2178+ // and around derived tables (e.g. `FROM ((SELECT ...)
2179+ // [AS alias])`) as well.
2180+ self . expect_token ( & Token :: RParen ) ?;
2181+
2182+ if let Some ( outer_alias) =
2183+ self . parse_optional_table_alias ( keywords:: RESERVED_FOR_TABLE_ALIAS ) ?
2184+ {
2185+ // Snowflake also allows specifying an alias *after* parens
2186+ // e.g. `FROM (mytable) AS alias`
2187+ match & mut table_and_joins. relation {
2188+ TableFactor :: Derived { alias, .. }
2189+ | TableFactor :: Table { alias, .. }
2190+ | TableFactor :: TableFunction { alias, .. } => {
2191+ // but not `FROM (mytable AS alias1) AS alias2`.
2192+ if let Some ( inner_alias) = alias {
2193+ return Err ( ParserError :: ParserError ( format ! (
2194+ "duplicate alias {}" ,
2195+ inner_alias
2196+ ) ) ) ;
2197+ }
2198+ // Act as if the alias was specified normally next
2199+ // to the table name: `(mytable) AS alias` ->
2200+ // `(mytable AS alias)`
2201+ alias. replace ( outer_alias) ;
2202+ }
2203+ TableFactor :: NestedJoin ( _) => unreachable ! ( ) ,
2204+ } ;
2205+ }
2206+ // Do not store the extra set of parens in the AST
2207+ Ok ( table_and_joins. relation )
2208+ } else {
2209+ // The SQL spec prohibits derived tables and bare tables from
2210+ // appearing alone in parentheses (e.g. `FROM (mytable)`)
2211+ self . expected ( "joined table" , self . peek_token ( ) )
2212+ }
21692213 } else {
21702214 let name = self . parse_object_name ( ) ?;
21712215 // Postgres, MSSQL: table-valued functions:
0 commit comments