@@ -479,6 +479,9 @@ impl<'a> Parser<'a> {
479
479
self . prev_token ( ) ;
480
480
self . parse_boxed_query ( ) . map ( Statement :: Query )
481
481
}
482
+ Keyword :: FROM if self . dialect . allow_from_first ( ) => {
483
+ Ok ( Statement :: Query ( self . parse_from_first_query ( None ) . map ( Box :: new) ?) )
484
+ }
482
485
Keyword :: TRUNCATE => self . parse_truncate ( ) ,
483
486
Keyword :: ATTACH => {
484
487
if dialect_of ! ( self is DuckDbDialect ) {
@@ -8535,91 +8538,131 @@ impl<'a> Parser<'a> {
8535
8538
settings : None ,
8536
8539
format_clause : None ,
8537
8540
} )
8541
+ } else if self . parse_keyword ( Keyword :: FROM ) && self . dialect . allow_from_first ( ) {
8542
+ self . parse_from_first_query ( with)
8538
8543
} else {
8539
8544
let body = self . parse_boxed_query_body ( self . dialect . prec_unknown ( ) ) ?;
8545
+ self . parse_query_extra ( body, with)
8546
+ }
8547
+ }
8540
8548
8541
- let order_by = self . parse_optional_order_by ( ) ? ;
8542
-
8543
- let mut limit = None ;
8544
- let mut offset = None ;
8549
+ /// Parse `SELECT` statements that start with a `FROM` clause,
8550
+ /// e.g. `FROM x SELECT foo` see <https://github.com/sqlparser-rs/sqlparser-rs/issues/1400> for rationale.
8551
+ fn parse_from_first_query ( & mut self , with : Option < With > ) -> Result < Query , ParserError > {
8552
+ let from = self . parse_comma_separated ( Parser :: parse_table_and_joins ) ? ;
8545
8553
8546
- for _x in 0 ..2 {
8547
- if limit. is_none ( ) && self . parse_keyword ( Keyword :: LIMIT ) {
8548
- limit = self . parse_limit ( ) ?
8554
+ if matches ! ( self . peek_token( ) . token, Token :: EOF | Token :: SemiColon ) {
8555
+ // no select part e.g. `FROM x`, this is equivalent to `FROM x SELECT *`
8556
+ return Ok ( Query {
8557
+ with,
8558
+ body : Box :: new ( SetExpr :: Select ( Box :: new ( Select {
8559
+ projection : vec ! [
8560
+ SelectItem :: Wildcard ( WildcardAdditionalOptions :: default ( ) ) ,
8561
+ ] ,
8562
+ from,
8563
+ ..Default :: default ( )
8564
+ } ) ) ) ,
8565
+ ..Default :: default ( )
8566
+ } ) ;
8567
+ } else {
8568
+ let body = self . parse_boxed_query_body ( self . dialect . prec_unknown ( ) ) ?;
8569
+ let mut query = self . parse_query_extra ( body, with) ?;
8570
+ if let SetExpr :: Select ( ref mut select) = * query. body {
8571
+ if select. from . is_empty ( ) {
8572
+ select. from = from;
8573
+ Ok ( query)
8574
+ } else {
8575
+ Err ( ParserError :: ParserError ( "FROM clause can only be used once" . to_string ( ) ) )
8549
8576
}
8577
+ } else {
8578
+ Err ( ParserError :: ParserError ( "leading FROM clause can only be used with SELECT" . to_string ( ) ) )
8579
+ }
8580
+ }
8581
+ }
8550
8582
8551
- if offset . is_none ( ) && self . parse_keyword ( Keyword :: OFFSET ) {
8552
- offset = Some ( self . parse_offset ( ) ? )
8553
- }
8583
+ /// Parse everything beyond the body of a query, i.e. everything after the `SELECT` clause
8584
+ fn parse_query_extra ( & mut self , body : Box < SetExpr > , with : Option < With > ) -> Result < Query , ParserError > {
8585
+ let order_by = self . parse_optional_order_by ( ) ? ;
8554
8586
8555
- if dialect_of ! ( self is GenericDialect | MySqlDialect | ClickHouseDialect )
8556
- && limit. is_some ( )
8557
- && offset. is_none ( )
8558
- && self . consume_token ( & Token :: Comma )
8559
- {
8560
- // MySQL style LIMIT x,y => LIMIT y OFFSET x.
8561
- // Check <https://dev.mysql.com/doc/refman/8.0/en/select.html> for more details.
8562
- offset = Some ( Offset {
8563
- value : limit. unwrap ( ) ,
8564
- rows : OffsetRows :: None ,
8565
- } ) ;
8566
- limit = Some ( self . parse_expr ( ) ?) ;
8567
- }
8587
+ let mut limit = None ;
8588
+ let mut offset = None ;
8589
+
8590
+ for _x in 0 ..2 {
8591
+ if limit. is_none ( ) && self . parse_keyword ( Keyword :: LIMIT ) {
8592
+ limit = self . parse_limit ( ) ?
8593
+ }
8594
+
8595
+ if offset. is_none ( ) && self . parse_keyword ( Keyword :: OFFSET ) {
8596
+ offset = Some ( self . parse_offset ( ) ?)
8568
8597
}
8569
8598
8570
- let limit_by = if dialect_of ! ( self is ClickHouseDialect | GenericDialect )
8571
- && self . parse_keyword ( Keyword :: BY )
8599
+ if dialect_of ! ( self is GenericDialect | MySqlDialect | ClickHouseDialect )
8600
+ && limit. is_some ( )
8601
+ && offset. is_none ( )
8602
+ && self . consume_token ( & Token :: Comma )
8572
8603
{
8573
- self . parse_comma_separated ( Parser :: parse_expr) ?
8574
- } else {
8575
- vec ! [ ]
8576
- } ;
8604
+ // MySQL style LIMIT x,y => LIMIT y OFFSET x.
8605
+ // Check <https://dev.mysql.com/doc/refman/8.0/en/select.html> for more details.
8606
+ offset = Some ( Offset {
8607
+ value : limit. unwrap ( ) ,
8608
+ rows : OffsetRows :: None ,
8609
+ } ) ;
8610
+ limit = Some ( self . parse_expr ( ) ?) ;
8611
+ }
8612
+ }
8577
8613
8578
- let settings = self . parse_settings ( ) ?;
8614
+ let limit_by = if dialect_of ! ( self is ClickHouseDialect | GenericDialect )
8615
+ && self . parse_keyword ( Keyword :: BY )
8616
+ {
8617
+ self . parse_comma_separated ( Parser :: parse_expr) ?
8618
+ } else {
8619
+ vec ! [ ]
8620
+ } ;
8579
8621
8580
- let fetch = if self . parse_keyword ( Keyword :: FETCH ) {
8581
- Some ( self . parse_fetch ( ) ?)
8582
- } else {
8583
- None
8584
- } ;
8622
+ let settings = self . parse_settings ( ) ?;
8585
8623
8586
- let mut for_clause = None ;
8587
- let mut locks = Vec :: new ( ) ;
8588
- while self . parse_keyword ( Keyword :: FOR ) {
8589
- if let Some ( parsed_for_clause) = self . parse_for_clause ( ) ? {
8590
- for_clause = Some ( parsed_for_clause) ;
8591
- break ;
8592
- } else {
8593
- locks. push ( self . parse_lock ( ) ?) ;
8594
- }
8624
+ let fetch = if self . parse_keyword ( Keyword :: FETCH ) {
8625
+ Some ( self . parse_fetch ( ) ?)
8626
+ } else {
8627
+ None
8628
+ } ;
8629
+
8630
+ let mut for_clause = None ;
8631
+ let mut locks = Vec :: new ( ) ;
8632
+ while self . parse_keyword ( Keyword :: FOR ) {
8633
+ if let Some ( parsed_for_clause) = self . parse_for_clause ( ) ? {
8634
+ for_clause = Some ( parsed_for_clause) ;
8635
+ break ;
8636
+ } else {
8637
+ locks. push ( self . parse_lock ( ) ?) ;
8595
8638
}
8596
- let format_clause = if dialect_of ! ( self is ClickHouseDialect | GenericDialect )
8597
- && self . parse_keyword ( Keyword :: FORMAT )
8598
- {
8599
- if self . parse_keyword ( Keyword :: NULL ) {
8600
- Some ( FormatClause :: Null )
8601
- } else {
8602
- let ident = self . parse_identifier ( false ) ?;
8603
- Some ( FormatClause :: Identifier ( ident) )
8604
- }
8639
+ }
8640
+ let format_clause = if dialect_of ! ( self is ClickHouseDialect | GenericDialect )
8641
+ && self . parse_keyword ( Keyword :: FORMAT )
8642
+ {
8643
+ if self . parse_keyword ( Keyword :: NULL ) {
8644
+ Some ( FormatClause :: Null )
8605
8645
} else {
8606
- None
8607
- } ;
8646
+ let ident = self . parse_identifier ( false ) ?;
8647
+ Some ( FormatClause :: Identifier ( ident) )
8648
+ }
8649
+ } else {
8650
+ None
8651
+ } ;
8608
8652
8609
- Ok ( Query {
8610
- with,
8611
- body,
8612
- order_by,
8613
- limit,
8614
- limit_by,
8615
- offset,
8616
- fetch,
8617
- locks,
8618
- for_clause,
8619
- settings,
8620
- format_clause,
8621
- } )
8622
- }
8653
+ Ok ( Query {
8654
+ with,
8655
+ body,
8656
+ order_by,
8657
+ limit,
8658
+ limit_by,
8659
+ offset,
8660
+ fetch,
8661
+ locks,
8662
+ for_clause,
8663
+ settings,
8664
+ format_clause,
8665
+ } )
8623
8666
}
8624
8667
8625
8668
fn parse_settings ( & mut self ) -> Result < Option < Vec < Setting > > , ParserError > {
0 commit comments