Resolve TODOs in parsing
Return error for queries containing non-ASCII characters Allow underscores in identifiers Add a delete statement test with spaces Remove trailing spaces and semicolons from tests and parsers Complete the multiple statement parser TODO
This commit is contained in:
parent
5d040f15f5
commit
de8c6164cf
7 changed files with 89 additions and 38 deletions
|
|
@ -1,6 +1,6 @@
|
|||
use crate::syntax::RawQuerySyntax;
|
||||
use minisql::{interpreter::DbSchema, operation::Operation};
|
||||
use nom::{branch::alt, IResult};
|
||||
use nom::{branch::alt, character::complete::{multispace0, char}, multi::many1, sequence::{delimited, terminated}, IResult};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::{
|
||||
|
|
@ -19,6 +19,7 @@ pub enum Error {
|
|||
ValidationError(#[from] ValidationError),
|
||||
}
|
||||
|
||||
/// Parse single statement
|
||||
fn parse_statement(input: &str) -> IResult<&str, RawQuerySyntax> {
|
||||
alt((
|
||||
parse_insert,
|
||||
|
|
@ -31,14 +32,59 @@ fn parse_statement(input: &str) -> IResult<&str, RawQuerySyntax> {
|
|||
))(input)
|
||||
}
|
||||
|
||||
/// Parse one or more statements
|
||||
fn parse_statement1(input: &str) -> IResult<&str, Vec<RawQuerySyntax>> {
|
||||
many1(terminated(parse_statement, delimited(multispace0, char(';'), multispace0)))(input)
|
||||
}
|
||||
|
||||
pub fn parse_and_validate(str_query: String, db_schema: &DbSchema) -> Result<Operation, Error> {
|
||||
if let Some(non_ascii) = str_query.chars().find(|c| c.len_utf8() > 1) {
|
||||
return Err(Error::ParsingError(
|
||||
format!("Non ASCII character found: {}", non_ascii)
|
||||
));
|
||||
}
|
||||
let (_, op) =
|
||||
parse_statement(str_query.as_str()).map_err(|err| Error::ParsingError(err.to_string()))?;
|
||||
|
||||
Ok(validate_operation(op, db_schema)?)
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn test_select() {
|
||||
// parse_and_validate("SELECT * FROM users;".to_string(), &Vec::new()).unwrap();
|
||||
// }
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::core::parse_statement1;
|
||||
use crate::parse_and_validate;
|
||||
use crate::Error;
|
||||
#[test]
|
||||
fn test_non_unicode() {
|
||||
let result = parse_and_validate(format!("SELECT * FROM users WHERE name = \"京\""), &Default::default());
|
||||
assert!(matches!(result, Err(Error::ParsingError(_))));
|
||||
if let Err(Error::ParsingError(err)) = result {
|
||||
assert_eq!(err, format!("Non ASCII character found: {}", '京'));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_two_select() {
|
||||
let (rest, sntx) = parse_statement1("SELECT * FROM users ; SELECT * FROM cities ; ").expect("should parse");
|
||||
assert_eq!(
|
||||
sntx.len(),
|
||||
2
|
||||
);
|
||||
assert_eq!(rest, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_three_insert_one_select() {
|
||||
let (rest, sntx) = parse_statement1(
|
||||
r#"INSERT INTO table1 (id, data) VALUES (u1, 2);
|
||||
SELECT * FROM users ;
|
||||
INSERT INTO table1 (id, data) VALUES (u4, 30) ;
|
||||
INSERT INTO table1 (id, data) VALUES (u5, 40) ;
|
||||
"#).expect("should parse");
|
||||
assert_eq!(
|
||||
sntx.len(),
|
||||
4
|
||||
);
|
||||
assert_eq!(rest, "");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue