@@ -2158,14 +2158,58 @@ impl<'a> Parser<'a> {
2158
2158
// recently consumed does not start a derived table (cases 1, 2, or 4).
2159
2159
// `maybe_parse` will ignore such an error and rewind to be after the opening '('.
2160
2160
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
+ }
2169
2213
} else {
2170
2214
let name = self . parse_object_name ( ) ?;
2171
2215
// Postgres, MSSQL: table-valued functions:
0 commit comments