@@ -40,6 +40,12 @@ pub enum IsOptional {
40
40
}
41
41
use IsOptional :: * ;
42
42
43
+ pub enum IsLateral {
44
+ Lateral ,
45
+ NotLateral ,
46
+ }
47
+ use IsLateral :: * ;
48
+
43
49
impl From < TokenizerError > for ParserError {
44
50
fn from ( e : TokenizerError ) -> Self {
45
51
ParserError :: TokenizerError ( format ! ( "{:?}" , e) )
@@ -1668,30 +1674,55 @@ impl Parser {
1668
1674
1669
1675
/// A table name or a parenthesized subquery, followed by optional `[AS] alias`
1670
1676
pub fn parse_table_factor ( & mut self ) -> Result < TableFactor , ParserError > {
1671
- let lateral = self . parse_keyword ( "LATERAL" ) ;
1677
+ if self . parse_keyword ( "LATERAL" ) {
1678
+ // LATERAL must always be followed by a subquery.
1679
+ if !self . consume_token ( & Token :: LParen ) {
1680
+ self . expected ( "subquery after LATERAL" , self . peek_token ( ) ) ?;
1681
+ }
1682
+ return self . parse_derived_table_factor ( Lateral ) ;
1683
+ }
1684
+
1672
1685
if self . consume_token ( & Token :: LParen ) {
1673
- if self . parse_keyword ( "SELECT" )
1674
- || self . parse_keyword ( "WITH" )
1675
- || self . parse_keyword ( "VALUES" )
1676
- {
1677
- self . prev_token ( ) ;
1678
- let subquery = Box :: new ( self . parse_query ( ) ?) ;
1679
- self . expect_token ( & Token :: RParen ) ?;
1680
- let alias = self . parse_optional_table_alias ( keywords:: RESERVED_FOR_TABLE_ALIAS ) ?;
1681
- Ok ( TableFactor :: Derived {
1682
- lateral,
1683
- subquery,
1684
- alias,
1685
- } )
1686
- } else if lateral {
1687
- parser_err ! ( "Expected subquery after LATERAL, found nested join" . to_string( ) )
1688
- } else {
1689
- let table_reference = self . parse_table_and_joins ( ) ?;
1690
- self . expect_token ( & Token :: RParen ) ?;
1691
- Ok ( TableFactor :: NestedJoin ( Box :: new ( table_reference) ) )
1686
+ let index = self . index ;
1687
+ // A left paren introduces either a derived table (i.e., a subquery)
1688
+ // or a nested join. It's nearly impossible to determine ahead of
1689
+ // time which it is... so we just try to parse both.
1690
+ //
1691
+ // Here's an example that demonstrates the complexity:
1692
+ // /-------------------------------------------------------\
1693
+ // | /-----------------------------------\ |
1694
+ // SELECT * FROM ( ( ( (SELECT 1) UNION (SELECT 2) ) AS t1 NATURAL JOIN t2 ) )
1695
+ // ^ ^ ^ ^
1696
+ // | | | |
1697
+ // | | | |
1698
+ // | | | (4) belongs to a SQLSetExpr::Query inside the subquery
1699
+ // | | (3) starts a derived table (subquery)
1700
+ // | (2) starts a nested join
1701
+ // (1) an additional set of parens around a nested join
1702
+ //
1703
+ match self . parse_derived_table_factor ( NotLateral ) {
1704
+ // The recently consumed '(' started a derived table, and we've
1705
+ // parsed the subquery, followed by the closing ')', and the
1706
+ // alias of the derived table. In the example above this is
1707
+ // case (3), and the next token would be `NATURAL`.
1708
+ Ok ( table_factor) => Ok ( table_factor) ,
1709
+ Err ( _) => {
1710
+ // The '(' we've recently consumed does not start a derived
1711
+ // table. For valid input this can happen either when the
1712
+ // token following the paren can't start a query (e.g. `foo`
1713
+ // in `FROM (foo NATURAL JOIN bar)`, or when the '(' we've
1714
+ // consumed is followed by another '(' that starts a
1715
+ // derived table, like (3), or another nested join (2).
1716
+ //
1717
+ // Ignore the error and back up to where we were before.
1718
+ // Either we'll be able to parse a valid nested join, or
1719
+ // we won't, and we'll return that error instead.
1720
+ self . index = index;
1721
+ let table_and_joins = self . parse_table_and_joins ( ) ?;
1722
+ self . expect_token ( & Token :: RParen ) ?;
1723
+ Ok ( TableFactor :: NestedJoin ( Box :: new ( table_and_joins) ) )
1724
+ }
1692
1725
}
1693
- } else if lateral {
1694
- self . expected ( "subquery after LATERAL" , self . peek_token ( ) )
1695
1726
} else {
1696
1727
let name = self . parse_object_name ( ) ?;
1697
1728
// Postgres, MSSQL: table-valued functions:
@@ -1721,6 +1752,23 @@ impl Parser {
1721
1752
}
1722
1753
}
1723
1754
1755
+ pub fn parse_derived_table_factor (
1756
+ & mut self ,
1757
+ lateral : IsLateral ,
1758
+ ) -> Result < TableFactor , ParserError > {
1759
+ let subquery = Box :: new ( self . parse_query ( ) ?) ;
1760
+ self . expect_token ( & Token :: RParen ) ?;
1761
+ let alias = self . parse_optional_table_alias ( keywords:: RESERVED_FOR_TABLE_ALIAS ) ?;
1762
+ Ok ( TableFactor :: Derived {
1763
+ lateral : match lateral {
1764
+ Lateral => true ,
1765
+ NotLateral => false ,
1766
+ } ,
1767
+ subquery,
1768
+ alias,
1769
+ } )
1770
+ }
1771
+
1724
1772
fn parse_join_constraint ( & mut self , natural : bool ) -> Result < JoinConstraint , ParserError > {
1725
1773
if natural {
1726
1774
Ok ( JoinConstraint :: Natural )
0 commit comments