@@ -256,10 +256,22 @@ impl ParserOptions {
256256 }
257257}
258258
259+ #[ derive( Copy , Clone ) ]
260+ enum ParserState {
261+ /// The default state of the parser.
262+ Normal ,
263+ /// The state when parsing a CONNECT BY expression. This allows parsing
264+ /// PRIOR expressions while still allowing prior as an identifier name
265+ /// in other contexts.
266+ ConnectBy ,
267+ }
268+
259269pub struct Parser < ' a > {
260270 tokens : Vec < TokenWithLocation > ,
261271 /// The index of the first unprocessed token in `self.tokens`
262272 index : usize ,
273+ /// The current state of the parser.
274+ state : ParserState ,
263275 /// The current dialect to use
264276 dialect : & ' a dyn Dialect ,
265277 /// Additional options that allow you to mix & match behavior
@@ -290,6 +302,7 @@ impl<'a> Parser<'a> {
290302 Self {
291303 tokens : vec ! [ ] ,
292304 index : 0 ,
305+ state : ParserState :: Normal ,
293306 dialect,
294307 recursion_counter : RecursionCounter :: new ( DEFAULT_REMAINING_DEPTH ) ,
295308 options : ParserOptions :: default ( ) ,
@@ -966,6 +979,10 @@ impl<'a> Parser<'a> {
966979 self . prev_token ( ) ;
967980 self . parse_bigquery_struct_literal ( )
968981 }
982+ Keyword :: PRIOR if matches ! ( self . state, ParserState :: ConnectBy ) => {
983+ let expr = self . parse_subexpr ( Self :: PLUS_MINUS_PREC ) ?;
984+ Ok ( Expr :: Prior ( Box :: new ( expr) ) )
985+ }
969986 // Here `w` is a word, check if it's a part of a multi-part
970987 // identifier, a function call, or a simple identifier:
971988 _ => match self . peek_token ( ) . token {
@@ -7154,7 +7171,7 @@ impl<'a> Parser<'a> {
71547171 // We parse the expression using a Pratt parser, as in `parse_expr()`.
71557172 // Start by parsing a restricted SELECT or a `(subquery)`:
71567173 let mut expr = if self . parse_keyword ( Keyword :: SELECT ) {
7157- SetExpr :: Select ( Box :: new ( self . parse_select ( ) ?) )
7174+ self . parse_select ( ) ?
71587175 } else if self . consume_token ( & Token :: LParen ) {
71597176 // CTEs are not allowed here, but the parser currently accepts them
71607177 let subquery = self . parse_query ( ) ?;
@@ -7242,7 +7259,7 @@ impl<'a> Parser<'a> {
72427259
72437260 /// Parse a restricted `SELECT` statement (no CTEs / `UNION` / `ORDER BY`),
72447261 /// assuming the initial `SELECT` was already consumed
7245- pub fn parse_select ( & mut self ) -> Result < Select , ParserError > {
7262+ pub fn parse_select ( & mut self ) -> Result < SetExpr , ParserError > {
72467263 let value_table_mode =
72477264 if dialect_of ! ( self is BigQueryDialect ) && self . parse_keyword ( Keyword :: AS ) {
72487265 if self . parse_keyword ( Keyword :: VALUE ) {
@@ -7294,6 +7311,18 @@ impl<'a> Parser<'a> {
72947311 vec ! [ ]
72957312 } ;
72967313
7314+ if distinct. is_none ( )
7315+ && top. is_none ( )
7316+ && into. is_none ( )
7317+ && !from. is_empty ( )
7318+ && self
7319+ . parse_one_of_keywords ( & [ Keyword :: START , Keyword :: CONNECT ] )
7320+ . is_some ( )
7321+ {
7322+ self . prev_token ( ) ;
7323+ return Ok ( SetExpr :: ConnectBy ( self . parse_connect_by ( projection, from) ?) ) ;
7324+ }
7325+
72977326 let mut lateral_views = vec ! [ ] ;
72987327 loop {
72997328 if self . parse_keywords ( & [ Keyword :: LATERAL , Keyword :: VIEW ] ) {
@@ -7377,7 +7406,7 @@ impl<'a> Parser<'a> {
73777406 None
73787407 } ;
73797408
7380- Ok ( Select {
7409+ Ok ( SetExpr :: Select ( Box :: new ( Select {
73817410 distinct,
73827411 top,
73837412 projection,
@@ -7393,6 +7422,48 @@ impl<'a> Parser<'a> {
73937422 named_window : named_windows,
73947423 qualify,
73957424 value_table_mode,
7425+ } ) ) )
7426+ }
7427+
7428+ fn with_state < T , F > ( & mut self , state : ParserState , mut f : F ) -> Result < T , ParserError >
7429+ where
7430+ F : FnMut ( & mut Parser ) -> Result < T , ParserError > ,
7431+ {
7432+ let current_state = self . state ;
7433+ self . state = state;
7434+ let res = f ( self ) ;
7435+ self . state = current_state;
7436+ res
7437+ }
7438+
7439+ pub fn parse_connect_by (
7440+ & mut self ,
7441+ projection : Vec < SelectItem > ,
7442+ from : Vec < TableWithJoins > ,
7443+ ) -> Result < ConnectBy , ParserError > {
7444+ debug_assert ! ( !from. is_empty( ) ) ;
7445+
7446+ let ( condition, relationships) = if self . parse_keywords ( & [ Keyword :: CONNECT , Keyword :: BY ] ) {
7447+ let relationships = self . with_state ( ParserState :: ConnectBy , |parser| {
7448+ parser. parse_comma_separated ( Parser :: parse_expr)
7449+ } ) ?;
7450+ self . expect_keywords ( & [ Keyword :: START , Keyword :: WITH ] ) ?;
7451+ let condition = self . parse_expr ( ) ?;
7452+ ( condition, relationships)
7453+ } else {
7454+ self . expect_keywords ( & [ Keyword :: START , Keyword :: WITH ] ) ?;
7455+ let condition = self . parse_expr ( ) ?;
7456+ self . expect_keywords ( & [ Keyword :: CONNECT , Keyword :: BY ] ) ?;
7457+ let relationships = self . with_state ( ParserState :: ConnectBy , |parser| {
7458+ parser. parse_comma_separated ( Parser :: parse_expr)
7459+ } ) ?;
7460+ ( condition, relationships)
7461+ } ;
7462+ Ok ( ConnectBy {
7463+ projection,
7464+ from,
7465+ condition,
7466+ relationships,
73967467 } )
73977468 }
73987469
0 commit comments