@@ -486,6 +486,18 @@ impl Parser {
486
486
true
487
487
}
488
488
489
+ pub fn expect_keyword ( & mut self , expected : & ' static str ) -> Result < ( ) , ParserError > {
490
+ if self . parse_keyword ( expected) {
491
+ Ok ( ( ) )
492
+ } else {
493
+ parser_err ! ( format!(
494
+ "Expected keyword {}, found {:?}" ,
495
+ expected,
496
+ self . peek_token( )
497
+ ) )
498
+ }
499
+ }
500
+
489
501
//TODO: this function is inconsistent and sometimes returns bool and sometimes fails
490
502
491
503
/// Consume the next token if it matches the expected token, otherwise return an error
@@ -1105,11 +1117,12 @@ impl Parser {
1105
1117
pub fn parse_select ( & mut self ) -> Result < ASTNode , ParserError > {
1106
1118
let projection = self . parse_expr_list ( ) ?;
1107
1119
1108
- let relation: Option < Box < ASTNode > > = if self . parse_keyword ( "FROM" ) {
1109
- //TODO: add support for JOIN
1110
- Some ( Box :: new ( self . parse_expr ( 0 ) ?) )
1120
+ let ( relation, joins) : ( Option < Box < ASTNode > > , Vec < Join > ) = if self . parse_keyword ( "FROM" ) {
1121
+ let relation = Some ( Box :: new ( self . parse_expr ( 0 ) ?) ) ;
1122
+ let joins = self . parse_joins ( ) ?;
1123
+ ( relation, joins)
1111
1124
} else {
1112
- None
1125
+ ( None , vec ! [ ] )
1113
1126
} ;
1114
1127
1115
1128
let selection = if self . parse_keyword ( "WHERE" ) {
@@ -1155,6 +1168,7 @@ impl Parser {
1155
1168
projection,
1156
1169
selection,
1157
1170
relation,
1171
+ joins,
1158
1172
limit,
1159
1173
order_by,
1160
1174
group_by,
@@ -1163,6 +1177,131 @@ impl Parser {
1163
1177
}
1164
1178
}
1165
1179
1180
+ fn parse_join_constraint ( & mut self , natural : bool ) -> Result < JoinConstraint , ParserError > {
1181
+ if natural {
1182
+ Ok ( JoinConstraint :: Natural )
1183
+ } else if self . parse_keyword ( "ON" ) {
1184
+ let constraint = self . parse_expr ( 0 ) ?;
1185
+ Ok ( JoinConstraint :: On ( constraint) )
1186
+ } else if self . parse_keyword ( "USING" ) {
1187
+ if self . consume_token ( & Token :: LParen ) ? {
1188
+ let attributes = self
1189
+ . parse_expr_list ( ) ?
1190
+ . into_iter ( )
1191
+ . map ( |ast_node| match ast_node {
1192
+ ASTNode :: SQLIdentifier ( ident) => Ok ( ident) ,
1193
+ unexpected => {
1194
+ parser_err ! ( format!( "Expected identifier, found {:?}" , unexpected) )
1195
+ }
1196
+ } )
1197
+ . collect :: < Result < Vec < String > , ParserError > > ( ) ?;
1198
+
1199
+ if self . consume_token ( & Token :: RParen ) ? {
1200
+ Ok ( JoinConstraint :: Using ( attributes) )
1201
+ } else {
1202
+ parser_err ! ( format!( "Expected token ')', found {:?}" , self . peek_token( ) ) )
1203
+ }
1204
+ } else {
1205
+ parser_err ! ( format!( "Expected token '(', found {:?}" , self . peek_token( ) ) )
1206
+ }
1207
+ } else {
1208
+ parser_err ! ( format!(
1209
+ "Unexpected token after JOIN: {:?}" ,
1210
+ self . peek_token( )
1211
+ ) )
1212
+ }
1213
+ }
1214
+
1215
+ fn parse_joins ( & mut self ) -> Result < Vec < Join > , ParserError > {
1216
+ let mut joins = vec ! [ ] ;
1217
+ loop {
1218
+ let natural = match & self . peek_token ( ) {
1219
+ Some ( Token :: Comma ) => {
1220
+ self . next_token ( ) ;
1221
+ let relation = self . parse_expr ( 0 ) ?;
1222
+ let join = Join {
1223
+ relation,
1224
+ join_operator : JoinOperator :: Implicit ,
1225
+ } ;
1226
+ joins. push ( join) ;
1227
+ continue ;
1228
+ }
1229
+ Some ( Token :: Keyword ( kw) ) if kw == "CROSS" => {
1230
+ self . next_token ( ) ;
1231
+ self . expect_keyword ( "JOIN" ) ?;
1232
+ let relation = self . parse_expr ( 0 ) ?;
1233
+ let join = Join {
1234
+ relation,
1235
+ join_operator : JoinOperator :: Cross ,
1236
+ } ;
1237
+ joins. push ( join) ;
1238
+ continue ;
1239
+ }
1240
+ Some ( Token :: Keyword ( kw) ) if kw == "NATURAL" => {
1241
+ self . next_token ( ) ;
1242
+ true
1243
+ }
1244
+ Some ( _) => false ,
1245
+ None => return Ok ( joins) ,
1246
+ } ;
1247
+
1248
+ let join = match & self . peek_token ( ) {
1249
+ Some ( Token :: Keyword ( kw) ) if kw == "INNER" => {
1250
+ self . next_token ( ) ;
1251
+ self . expect_keyword ( "JOIN" ) ?;
1252
+ Join {
1253
+ relation : self . parse_expr ( 0 ) ?,
1254
+ join_operator : JoinOperator :: Inner ( self . parse_join_constraint ( natural) ?) ,
1255
+ }
1256
+ }
1257
+ Some ( Token :: Keyword ( kw) ) if kw == "JOIN" => {
1258
+ self . next_token ( ) ;
1259
+ Join {
1260
+ relation : self . parse_expr ( 0 ) ?,
1261
+ join_operator : JoinOperator :: Inner ( self . parse_join_constraint ( natural) ?) ,
1262
+ }
1263
+ }
1264
+ Some ( Token :: Keyword ( kw) ) if kw == "LEFT" => {
1265
+ self . next_token ( ) ;
1266
+ self . parse_keyword ( "OUTER" ) ;
1267
+ self . expect_keyword ( "JOIN" ) ?;
1268
+ Join {
1269
+ relation : self . parse_expr ( 0 ) ?,
1270
+ join_operator : JoinOperator :: LeftOuter (
1271
+ self . parse_join_constraint ( natural) ?,
1272
+ ) ,
1273
+ }
1274
+ }
1275
+ Some ( Token :: Keyword ( kw) ) if kw == "RIGHT" => {
1276
+ self . next_token ( ) ;
1277
+ self . parse_keyword ( "OUTER" ) ;
1278
+ self . expect_keyword ( "JOIN" ) ?;
1279
+ Join {
1280
+ relation : self . parse_expr ( 0 ) ?,
1281
+ join_operator : JoinOperator :: RightOuter (
1282
+ self . parse_join_constraint ( natural) ?,
1283
+ ) ,
1284
+ }
1285
+ }
1286
+ Some ( Token :: Keyword ( kw) ) if kw == "FULL" => {
1287
+ self . next_token ( ) ;
1288
+ self . parse_keyword ( "OUTER" ) ;
1289
+ self . expect_keyword ( "JOIN" ) ?;
1290
+ Join {
1291
+ relation : self . parse_expr ( 0 ) ?,
1292
+ join_operator : JoinOperator :: FullOuter (
1293
+ self . parse_join_constraint ( natural) ?,
1294
+ ) ,
1295
+ }
1296
+ }
1297
+ _ => break ,
1298
+ } ;
1299
+ joins. push ( join) ;
1300
+ }
1301
+
1302
+ Ok ( joins)
1303
+ }
1304
+
1166
1305
/// Parse an INSERT statement
1167
1306
pub fn parse_insert ( & mut self ) -> Result < ASTNode , ParserError > {
1168
1307
self . parse_keyword ( "INTO" ) ;
0 commit comments