@@ -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 {
@@ -5894,12 +5911,15 @@ impl<'a> Parser<'a> {
58945911 ) ?,
58955912 } ,
58965913 // Case when Snowflake Semi-structured data like key:value
5914+ // FIXME: Find a better way to deal with this than exhaustively
5915+ // listing every keyword allowed here.
58975916 Keyword :: NoKeyword
58985917 | Keyword :: LOCATION
58995918 | Keyword :: TYPE
59005919 | Keyword :: DATE
59015920 | Keyword :: START
59025921 | Keyword :: END
5922+ | Keyword :: DATA
59035923 if dialect_of ! ( self is SnowflakeDialect | GenericDialect ) =>
59045924 {
59055925 Ok ( Value :: UnQuotedString ( w. value ) )
@@ -7154,7 +7174,7 @@ impl<'a> Parser<'a> {
71547174 // We parse the expression using a Pratt parser, as in `parse_expr()`.
71557175 // Start by parsing a restricted SELECT or a `(subquery)`:
71567176 let mut expr = if self . parse_keyword ( Keyword :: SELECT ) {
7157- SetExpr :: Select ( Box :: new ( self . parse_select ( ) ?) )
7177+ self . parse_select ( ) ?
71587178 } else if self . consume_token ( & Token :: LParen ) {
71597179 // CTEs are not allowed here, but the parser currently accepts them
71607180 let subquery = self . parse_query ( ) ?;
@@ -7242,7 +7262,7 @@ impl<'a> Parser<'a> {
72427262
72437263 /// Parse a restricted `SELECT` statement (no CTEs / `UNION` / `ORDER BY`),
72447264 /// assuming the initial `SELECT` was already consumed
7245- pub fn parse_select ( & mut self ) -> Result < Select , ParserError > {
7265+ pub fn parse_select ( & mut self ) -> Result < SetExpr , ParserError > {
72467266 let value_table_mode =
72477267 if dialect_of ! ( self is BigQueryDialect ) && self . parse_keyword ( Keyword :: AS ) {
72487268 if self . parse_keyword ( Keyword :: VALUE ) {
@@ -7294,6 +7314,18 @@ impl<'a> Parser<'a> {
72947314 vec ! [ ]
72957315 } ;
72967316
7317+ if distinct. is_none ( )
7318+ && top. is_none ( )
7319+ && into. is_none ( )
7320+ && !from. is_empty ( )
7321+ && self
7322+ . parse_one_of_keywords ( & [ Keyword :: START , Keyword :: CONNECT ] )
7323+ . is_some ( )
7324+ {
7325+ self . prev_token ( ) ;
7326+ return Ok ( SetExpr :: ConnectBy ( self . parse_connect_by ( projection, from) ?) ) ;
7327+ }
7328+
72977329 let mut lateral_views = vec ! [ ] ;
72987330 loop {
72997331 if self . parse_keywords ( & [ Keyword :: LATERAL , Keyword :: VIEW ] ) {
@@ -7377,7 +7409,7 @@ impl<'a> Parser<'a> {
73777409 None
73787410 } ;
73797411
7380- Ok ( Select {
7412+ Ok ( SetExpr :: Select ( Box :: new ( Select {
73817413 distinct,
73827414 top,
73837415 projection,
@@ -7393,6 +7425,48 @@ impl<'a> Parser<'a> {
73937425 named_window : named_windows,
73947426 qualify,
73957427 value_table_mode,
7428+ } ) ) )
7429+ }
7430+
7431+ fn with_state < T , F > ( & mut self , state : ParserState , mut f : F ) -> Result < T , ParserError >
7432+ where
7433+ F : FnMut ( & mut Parser ) -> Result < T , ParserError > ,
7434+ {
7435+ let current_state = self . state ;
7436+ self . state = state;
7437+ let res = f ( self ) ;
7438+ self . state = current_state;
7439+ res
7440+ }
7441+
7442+ pub fn parse_connect_by (
7443+ & mut self ,
7444+ projection : Vec < SelectItem > ,
7445+ from : Vec < TableWithJoins > ,
7446+ ) -> Result < ConnectBy , ParserError > {
7447+ debug_assert ! ( !from. is_empty( ) ) ;
7448+
7449+ let ( condition, relationships) = if self . parse_keywords ( & [ Keyword :: CONNECT , Keyword :: BY ] ) {
7450+ let relationships = self . with_state ( ParserState :: ConnectBy , |parser| {
7451+ parser. parse_comma_separated ( Parser :: parse_expr)
7452+ } ) ?;
7453+ self . expect_keywords ( & [ Keyword :: START , Keyword :: WITH ] ) ?;
7454+ let condition = self . parse_expr ( ) ?;
7455+ ( condition, relationships)
7456+ } else {
7457+ self . expect_keywords ( & [ Keyword :: START , Keyword :: WITH ] ) ?;
7458+ let condition = self . parse_expr ( ) ?;
7459+ self . expect_keywords ( & [ Keyword :: CONNECT , Keyword :: BY ] ) ?;
7460+ let relationships = self . with_state ( ParserState :: ConnectBy , |parser| {
7461+ parser. parse_comma_separated ( Parser :: parse_expr)
7462+ } ) ?;
7463+ ( condition, relationships)
7464+ } ;
7465+ Ok ( ConnectBy {
7466+ projection,
7467+ from,
7468+ condition,
7469+ relationships,
73967470 } )
73977471 }
73987472
0 commit comments