diff --git a/src/common.rs b/src/common.rs index 100f935..753dd4d 100644 --- a/src/common.rs +++ b/src/common.rs @@ -890,7 +890,7 @@ pub fn field_definition_expr(i: &[u8]) -> IResult<&[u8], Vec IResult<&[u8], Vec> { - many0(terminated(schema_table_reference, opt(ws_sep_comma)))(i) + many1(terminated(schema_table_reference, opt(ws_sep_comma)))(i) } // Integer literal value diff --git a/src/select.rs b/src/select.rs index c4bdb6d..86ee372 100644 --- a/src/select.rs +++ b/src/select.rs @@ -274,15 +274,15 @@ pub fn selection(i: &[u8]) -> IResult<&[u8], SelectStatement> { } pub fn nested_selection(i: &[u8]) -> IResult<&[u8], SelectStatement> { - let ( - remaining_input, - (_, _, distinct, _, fields, _, tables, join, where_clause, group_by, order, limit), - ) = tuple(( + let (remaining_input, (_, _, distinct, _, fields)) = tuple(( tag_no_case("select"), multispace1, opt(tag_no_case("distinct")), multispace0, field_definition_expr, + ))(i)?; + + let (remaining_input, from_clause) = opt(tuple(( delimited(multispace0, tag_no_case("from"), multispace0), table_list, many0(join_clause), @@ -290,20 +290,24 @@ pub fn nested_selection(i: &[u8]) -> IResult<&[u8], SelectStatement> { opt(group_by_clause), opt(order_clause), opt(limit_clause), - ))(i)?; - Ok(( - remaining_input, - SelectStatement { - tables, - distinct: distinct.is_some(), - fields, - join, - where_clause, - group_by, - order, - limit, - }, - )) + )))(remaining_input)?; + + let mut result = SelectStatement { + distinct: distinct.is_some(), + fields, + ..Default::default() + }; + + if let Some((_, tables, join, where_clause, group_by, order, limit)) = from_clause { + result.tables = tables; + result.join = join; + result.where_clause = where_clause; + result.group_by = group_by; + result.order = order; + result.limit = limit; + } + + Ok((remaining_input, result)) } #[cfg(test)] @@ -341,6 +345,13 @@ mod tests { ); } + #[test] + fn select_without_table() { + let qstring = "SELECT * FROM;"; + let res = selection(qstring.as_bytes()); + assert!(res.is_err(), "!{:?}.is_err()", res); + } + #[test] fn more_involved_select() { let qstring = "SELECT users.id, users.name FROM users;"; @@ -533,7 +544,7 @@ mod tests { tables: vec![Table { name: String::from("PaperTag"), alias: Some(String::from("t")), - schema: None, + schema: None, },], fields: vec![FieldDefinitionExpression::All], ..Default::default() @@ -554,7 +565,7 @@ mod tests { tables: vec![Table { name: String::from("PaperTag"), alias: Some(String::from("t")), - schema: Some(String::from("db1")), + schema: Some(String::from("db1")), },], fields: vec![FieldDefinitionExpression::All], ..Default::default() diff --git a/tests/lib.rs b/tests/lib.rs index e0d7263..8a30fea 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -213,6 +213,6 @@ fn parse_autoincrement() { #[test] fn parse_select() { let (ok, fail) = parse_file("tests/select.txt"); - assert_eq!(fail, 0); + assert_eq!(fail, 1); assert_eq!(ok, 27); } diff --git a/tests/select.txt b/tests/select.txt index 84b65b9..36a9729 100644 --- a/tests/select.txt +++ b/tests/select.txt @@ -1,3 +1,4 @@ +select * from; select a + b from c; select a + 2 from c;