@@ -23,6 +23,8 @@ pub trait SelectStatementParser {
23
23
24
24
fn parse_select_from_clause ( & mut self ) -> Result < Option < SelectFrom > , ParsingError > ;
25
25
26
+ fn parse_select_from_clause_subquery ( & mut self ) -> Result < SelectFrom , ParsingError > ;
27
+
26
28
fn parse_alias_if_exists ( & mut self ) -> Result < Option < String > , ParsingError > ;
27
29
}
28
30
@@ -101,85 +103,87 @@ impl<'a> SelectStatementParser for Parser<'a> {
101
103
102
104
fn parse_select_from_clause ( & mut self ) -> Result < Option < SelectFrom > , ParsingError > {
103
105
if let Ok ( Keyword :: From ) = self . peek_as_keyword ( ) {
104
- dbg ! ( "parse_select_from_clause" ) ;
105
106
self . consume_as_keyword ( Keyword :: From ) ?;
107
+ return Ok ( Some ( self . parse_select_from_clause_subquery ( ) ?) ) ;
108
+ }
109
+ Ok ( None )
110
+ }
111
+
112
+ fn parse_select_from_clause_subquery ( & mut self ) -> Result < SelectFrom , ParsingError > {
113
+ dbg ! ( "parse_select_from_clause" ) ;
106
114
115
+ dbg ! ( & self . peek_token( ) ) ;
116
+ if self . peek_as ( TokenType :: LeftParen ) . is_ok ( ) {
117
+ self . consume_as ( TokenType :: LeftParen ) ?;
107
118
dbg ! ( & self . peek_token( ) ) ;
119
+
120
+ if let Ok ( Keyword :: Select ) = self . peek_as_keyword ( ) {
121
+ let subquery = self . parse_select_statement ( ) ?;
122
+ // Here the right parenthesis is mandatory
123
+ self . consume_as ( TokenType :: RightParen ) ?;
124
+ let alias = self . parse_alias_if_exists ( ) ?;
125
+ return Ok ( SelectFrom :: Subquery ( SelectFromSubquery {
126
+ subquery : Box :: new ( subquery) ,
127
+ alias,
128
+ } ) ) ;
129
+ } else {
130
+ let mut froms = Vec :: new ( ) ;
131
+ loop {
132
+ dbg ! ( "parse_select_from_clause" ) ;
133
+ let table_or_subquery = self . parse_select_from_clause_subquery ( ) ?;
134
+ dbg ! ( & table_or_subquery) ;
135
+ froms. push ( table_or_subquery) ;
136
+
137
+ if self . consume_as ( TokenType :: Comma ) . is_err ( ) {
138
+ break ;
139
+ }
140
+ }
141
+ // Here the right parenthesis is mandatory
142
+ self . consume_as ( TokenType :: RightParen ) ?;
143
+ return Ok ( SelectFrom :: Froms ( froms) ) ;
144
+ } ;
145
+ }
146
+
147
+ if let Ok ( id) = self . parse_identifier ( ) {
148
+ dbg ! ( "parse_select_from_clause" ) ;
108
149
if self . peek_as ( TokenType :: LeftParen ) . is_ok ( ) {
109
150
self . consume_as ( TokenType :: LeftParen ) ?;
110
- dbg ! ( & self . peek_token( ) ) ;
111
-
112
- if let Ok ( Keyword :: Select ) = self . peek_as_keyword ( ) {
113
- dbg ! ( & self . peek_token( ) ) ;
114
- let subquery = self . parse_select_statement ( ) ?;
115
- dbg ! ( & subquery) ;
116
-
117
- // Here the right parenthesis is mandatory
118
- self . consume_as ( TokenType :: RightParen ) ?;
119
- if let Ok ( Keyword :: As ) = self . peek_as_keyword ( ) {
120
- self . consume_as_keyword ( Keyword :: As ) ?;
121
- let alias = self . consume_as_id ( ) ?;
122
- return Ok ( Some ( SelectFrom :: Subquery ( SelectFromSubquery {
123
- subquery : Box :: new ( subquery) ,
124
- alias : Some ( alias. to_string ( ) ) ,
125
- } ) ) ) ;
126
- }
127
151
128
- if let Ok ( value) = self . peek_as_id ( ) {
129
- return Ok ( Some ( SelectFrom :: Subquery ( SelectFromSubquery {
130
- subquery : Box :: new ( subquery) ,
131
- alias : Some ( value. to_string ( ) ) ,
132
- } ) ) ) ;
152
+ let arguments = self . parse_comma_separated_expressions ( ) ?;
153
+
154
+ self . consume_as ( TokenType :: RightParen ) ?;
155
+ let alias = self . parse_alias_if_exists ( ) ?;
156
+ return Ok ( SelectFrom :: Function ( SelectFromFunction {
157
+ function_name : id,
158
+ arguments,
159
+ alias,
160
+ } ) ) ;
161
+ } else {
162
+ let alias = self . parse_alias_if_exists ( ) ?;
163
+
164
+ let indexed_type = {
165
+ if self . consume_as_keyword ( Keyword :: Indexed ) . is_ok ( ) {
166
+ self . consume_as_keyword ( Keyword :: By ) ?;
167
+ Some ( IndexedType :: Indexed ( self . consume_as_id ( ) ?) )
168
+ } else if self . consume_as_keyword ( Keyword :: Not ) . is_ok ( ) {
169
+ self . consume_as_keyword ( Keyword :: Indexed ) ?;
170
+ Some ( IndexedType :: NotIndexed )
171
+ } else {
172
+ None
133
173
}
174
+ } ;
134
175
135
- return Ok ( Some ( SelectFrom :: Subquery ( SelectFromSubquery {
136
- subquery : Box :: new ( subquery) ,
137
- alias : None ,
138
- } ) ) ) ;
139
- }
140
- }
141
-
142
- if let Ok ( id) = self . parse_identifier ( ) {
143
- dbg ! ( "parse_select_from_clause" ) ;
144
- if self . peek_as ( TokenType :: LeftParen ) . is_ok ( ) {
145
- self . consume_as ( TokenType :: LeftParen ) ?;
146
-
147
- let arguments = self . parse_comma_separated_expressions ( ) ?;
148
-
149
- self . consume_as ( TokenType :: RightParen ) ?;
150
- let alias = self . parse_alias_if_exists ( ) ?;
151
- return Ok ( Some ( SelectFrom :: Function ( SelectFromFunction {
152
- function_name : id,
153
- arguments,
154
- alias,
155
- } ) ) ) ;
156
- } else {
157
- let alias = self . parse_alias_if_exists ( ) ?;
158
-
159
- let indexed_type = {
160
- if self . consume_as_keyword ( Keyword :: Indexed ) . is_ok ( ) {
161
- self . consume_as_keyword ( Keyword :: By ) ?;
162
- Some ( IndexedType :: Indexed ( self . consume_as_id ( ) ?) )
163
- } else if self . consume_as_keyword ( Keyword :: Not ) . is_ok ( ) {
164
- self . consume_as_keyword ( Keyword :: Indexed ) ?;
165
- Some ( IndexedType :: NotIndexed )
166
- } else {
167
- None
168
- }
169
- } ;
170
-
171
- return Ok ( Some ( SelectFrom :: Table ( SelectFromTable {
172
- table_id : id,
173
- alias,
174
- indexed_type,
175
- } ) ) ) ;
176
- }
176
+ return Ok ( SelectFrom :: Table ( SelectFromTable {
177
+ table_id : id,
178
+ alias,
179
+ indexed_type,
180
+ } ) ) ;
177
181
}
178
-
179
- // TODO: Parse table-or-subquery
180
- return Ok ( None ) ;
181
182
}
182
- Ok ( None )
183
+ // TODO: improve this error message
184
+ Err ( ParsingError :: UnexpectedToken (
185
+ self . peek_token ( ) ?. to_string ( ) ,
186
+ ) )
183
187
}
184
188
185
189
fn parse_alias_if_exists ( & mut self ) -> Result < Option < String > , ParsingError > {
@@ -670,3 +674,82 @@ mod test_select_from_table_function {
670
674
) ;
671
675
}
672
676
}
677
+
678
+ #[ cfg( test) ]
679
+ mod test_select_from_comma_separated_table_or_subqueries {
680
+ use super :: test_utils:: select_statement_with_from;
681
+ use crate :: expression:: test_utils:: numeric_literal_expression;
682
+ use crate :: parser:: test_utils:: * ;
683
+ use crate :: {
684
+ Identifier , IndexedType , SelectFrom , SelectFromFunction , SelectFromSubquery ,
685
+ SelectFromTable , Statement ,
686
+ } ;
687
+
688
+ #[ test]
689
+ fn test_select_from_comma_separated_table_or_subqueries ( ) {
690
+ let expected_statement = select_statement_with_from ( SelectFrom :: Froms ( vec ! [
691
+ SelectFrom :: Table ( SelectFromTable :: from( Identifier :: Single (
692
+ "table_1" . to_string( ) ,
693
+ ) ) ) ,
694
+ SelectFrom :: Table ( SelectFromTable :: from( Identifier :: Compound ( vec![
695
+ "schema2" . to_string( ) ,
696
+ "table2" . to_string( ) ,
697
+ ] ) ) ) ,
698
+ SelectFrom :: Table ( SelectFromTable {
699
+ table_id: Identifier :: Compound ( vec![ "schema3" . to_string( ) , "table3" . to_string( ) ] ) ,
700
+ alias: Some ( "table3_alias" . to_string( ) ) ,
701
+ indexed_type: None ,
702
+ } ) ,
703
+ SelectFrom :: Table ( SelectFromTable {
704
+ table_id: Identifier :: Single ( "indexed_table" . to_string( ) ) ,
705
+ alias: Some ( "t1" . to_string( ) ) ,
706
+ indexed_type: Some ( IndexedType :: Indexed ( "index_1" . to_string( ) ) ) ,
707
+ } ) ,
708
+ SelectFrom :: Table ( SelectFromTable {
709
+ table_id: Identifier :: Single ( "not_indexed_table" . to_string( ) ) ,
710
+ alias: Some ( "t2" . to_string( ) ) ,
711
+ indexed_type: Some ( IndexedType :: NotIndexed ) ,
712
+ } ) ,
713
+ SelectFrom :: Function ( SelectFromFunction {
714
+ function_name: Identifier :: Compound ( vec![
715
+ "schema4" . to_string( ) ,
716
+ "function_1" . to_string( ) ,
717
+ ] ) ,
718
+ arguments: vec![
719
+ numeric_literal_expression( "1" ) ,
720
+ numeric_literal_expression( "2" ) ,
721
+ numeric_literal_expression( "3" ) ,
722
+ ] ,
723
+ alias: Some ( "f1" . to_string( ) ) ,
724
+ } ) ,
725
+ SelectFrom :: Subquery ( SelectFromSubquery {
726
+ subquery: Box :: new( select_statement_with_from( SelectFrom :: Table (
727
+ SelectFromTable :: from( Identifier :: Single ( "table_2" . to_string( ) ) ) ,
728
+ ) ) ) ,
729
+ alias: Some ( "select_alias" . to_string( ) ) ,
730
+ } ) ,
731
+ SelectFrom :: Froms ( vec![
732
+ SelectFrom :: Table ( SelectFromTable :: from( Identifier :: Single (
733
+ "froms_1" . to_string( ) ,
734
+ ) ) ) ,
735
+ SelectFrom :: Table ( SelectFromTable :: from( Identifier :: Single (
736
+ "froms_2" . to_string( ) ,
737
+ ) ) ) ,
738
+ ] ) ,
739
+ ] ) ) ;
740
+
741
+ run_sunny_day_test (
742
+ "SELECT * FROM (
743
+ table_1,
744
+ schema2.table2,
745
+ schema3.table3 as table3_alias,
746
+ indexed_table as t1 INDEXED BY index_1,
747
+ not_indexed_table as t2 NOT INDEXED,
748
+ schema4.function_1(1, 2, 3) as f1,
749
+ (SELECT * FROM table_2) as select_alias,
750
+ (froms_1, froms_2)
751
+ )" ,
752
+ Statement :: Select ( expected_statement) ,
753
+ ) ;
754
+ }
755
+ }
0 commit comments