@@ -362,32 +362,7 @@ impl<'a> Parser<'a> {
362362 vec ! [ ]
363363 } ;
364364 let over = if self . parse_keyword ( Keyword :: OVER ) {
365- // TBD: support window names (`OVER mywin`) in place of inline specification
366- self . expect_token ( & Token :: LParen ) ?;
367- let partition_by = if self . parse_keywords ( & [ Keyword :: PARTITION , Keyword :: BY ] ) {
368- // a list of possibly-qualified column names
369- self . parse_comma_separated ( Parser :: parse_expr) ?
370- } else {
371- vec ! [ ]
372- } ;
373- let order_by = if self . parse_keywords ( & [ Keyword :: ORDER , Keyword :: BY ] ) {
374- self . parse_comma_separated ( Parser :: parse_order_by_expr) ?
375- } else {
376- vec ! [ ]
377- } ;
378- let window_frame = if !self . consume_token ( & Token :: RParen ) {
379- let window_frame = self . parse_window_frame ( ) ?;
380- self . expect_token ( & Token :: RParen ) ?;
381- Some ( window_frame)
382- } else {
383- None
384- } ;
385-
386- Some ( WindowSpec {
387- partition_by,
388- order_by,
389- window_frame,
390- } )
365+ Some ( self . parse_window_spec ( ) ?)
391366 } else {
392367 None
393368 } ;
@@ -438,20 +413,68 @@ impl<'a> Parser<'a> {
438413 }
439414 }
440415
441- pub fn parse_window_frame_units ( & mut self ) -> Result < WindowFrameUnits , ParserError > {
442- match self . next_token ( ) {
416+ pub fn parse_named_window_expr ( & mut self ) -> Result < ( Ident , WindowSpec ) , ParserError > {
417+ let ident = self . parse_identifier ( ) ?;
418+ self . expect_keyword ( Keyword :: AS ) ?;
419+ let spec = self . parse_window_spec ( ) ?;
420+ return Ok ( ( ident, spec) ) ;
421+ }
422+
423+ pub fn parse_window_spec ( & mut self ) -> Result < WindowSpec , ParserError > {
424+ if self . consume_token ( & Token :: LParen ) {
425+ let partition_by = if self . parse_keywords ( & [ Keyword :: PARTITION , Keyword :: BY ] ) {
426+ // a list of possibly-qualified column names
427+ self . parse_comma_separated ( Parser :: parse_expr) ?
428+ } else {
429+ vec ! [ ]
430+ } ;
431+ let order_by = if self . parse_keywords ( & [ Keyword :: ORDER , Keyword :: BY ] ) {
432+ self . parse_comma_separated ( Parser :: parse_order_by_expr) ?
433+ } else {
434+ vec ! [ ]
435+ } ;
436+ let window_frame = self . parse_window_frame ( ) ?;
437+
438+ let found_rparen = self . consume_token ( & Token :: RParen ) ;
439+ if partition_by. is_empty ( ) && order_by. is_empty ( ) && window_frame. is_none ( ) && !found_rparen {
440+ // try parsing a named window if we failed to parse any part of
441+ // a window spec and we haven't reached the rparen yet
442+ let ident = self . parse_identifier ( ) ?;
443+ self . expect_token ( & Token :: RParen ) ?;
444+ return Ok ( WindowSpec :: Named ( ident) ) ;
445+ }
446+
447+ Ok ( WindowSpec :: Inline ( InlineWindowSpec {
448+ partition_by,
449+ order_by,
450+ window_frame,
451+ } ) )
452+ } else {
453+ // named windows don't need parens
454+ Ok ( WindowSpec :: Named ( self . parse_identifier ( ) ?) )
455+ }
456+ }
457+
458+ pub fn consume_window_frame_units ( & mut self ) -> Result < Option < WindowFrameUnits > , ParserError > {
459+ let units = match self . peek_token ( ) {
443460 Token :: Word ( w) => match w. keyword {
444- Keyword :: ROWS => Ok ( WindowFrameUnits :: Rows ) ,
445- Keyword :: RANGE => Ok ( WindowFrameUnits :: Range ) ,
446- Keyword :: GROUPS => Ok ( WindowFrameUnits :: Groups ) ,
447- _ => self . expected ( "ROWS, RANGE, GROUPS" , Token :: Word ( w ) ) ? ,
461+ Keyword :: ROWS => WindowFrameUnits :: Rows ,
462+ Keyword :: RANGE => WindowFrameUnits :: Range ,
463+ Keyword :: GROUPS => WindowFrameUnits :: Groups ,
464+ _ => return Ok ( None ) ,
448465 } ,
449- unexpected => self . expected ( "ROWS, RANGE, GROUPS" , unexpected) ,
450- }
466+ _ => return Ok ( None ) ,
467+ } ;
468+ self . next_token ( ) ; // consume token
469+ Ok ( Some ( units) )
451470 }
452471
453- pub fn parse_window_frame ( & mut self ) -> Result < WindowFrame , ParserError > {
454- let units = self . parse_window_frame_units ( ) ?;
472+ pub fn parse_window_frame ( & mut self ) -> Result < Option < WindowFrame > , ParserError > {
473+ let units = if let Some ( units) = self . consume_window_frame_units ( ) ? {
474+ units
475+ } else {
476+ return Ok ( None ) ;
477+ } ;
455478 let ( start_bound, end_bound) = if self . parse_keyword ( Keyword :: BETWEEN ) {
456479 let start_bound = self . parse_window_frame_bound ( ) ?;
457480 self . expect_keyword ( Keyword :: AND ) ?;
@@ -460,11 +483,11 @@ impl<'a> Parser<'a> {
460483 } else {
461484 ( self . parse_window_frame_bound ( ) ?, None )
462485 } ;
463- Ok ( WindowFrame {
486+ Ok ( Some ( WindowFrame {
464487 units,
465488 start_bound,
466489 end_bound,
467- } )
490+ } ) )
468491 }
469492
470493 /// Parse `CURRENT ROW` or `{ <positive number> | UNBOUNDED } { PRECEDING | FOLLOWING }`
@@ -2324,6 +2347,13 @@ impl<'a> Parser<'a> {
23242347 None
23252348 } ;
23262349
2350+ // https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#window_clause
2351+ let windows = if self . parse_keyword ( Keyword :: WINDOW ) {
2352+ self . parse_comma_separated ( Parser :: parse_named_window_expr) ?
2353+ } else {
2354+ vec ! [ ]
2355+ } ;
2356+
23272357 Ok ( Select {
23282358 distinct,
23292359 top,
@@ -2333,6 +2363,7 @@ impl<'a> Parser<'a> {
23332363 group_by,
23342364 having,
23352365 qualify,
2366+ windows,
23362367 } )
23372368 }
23382369
0 commit comments