formatting
This commit is contained in:
parent
ad98cfafb2
commit
c25c6edc6a
29 changed files with 886 additions and 571 deletions
|
|
@ -1,10 +1,19 @@
|
|||
use minisql::type_system::DbType;
|
||||
use nom::{
|
||||
branch::alt, bytes::complete::{tag, take_while}, character::{complete::{alphanumeric1, anychar, char, multispace0, multispace1}, is_alphanumeric}, combinator::peek, error::make_error, sequence::{delimited, terminated}, IResult, Parser
|
||||
branch::alt,
|
||||
bytes::complete::{tag, take_while},
|
||||
character::{
|
||||
complete::{alphanumeric1, anychar, char, multispace0, multispace1},
|
||||
is_alphanumeric,
|
||||
},
|
||||
combinator::peek,
|
||||
error::make_error,
|
||||
sequence::{delimited, terminated},
|
||||
IResult, Parser,
|
||||
};
|
||||
|
||||
use crate::syntax::Condition;
|
||||
use super::literal::parse_literal;
|
||||
use crate::syntax::Condition;
|
||||
|
||||
pub fn parse_table_name(input: &str) -> IResult<&str, &str> {
|
||||
alt((
|
||||
|
|
@ -16,11 +25,9 @@ pub fn parse_table_name(input: &str) -> IResult<&str, &str> {
|
|||
pub fn parse_identifier(input: &str) -> IResult<&str, &str> {
|
||||
let (_, first) = peek(anychar)(input)?;
|
||||
if first.is_alphabetic() || first == '_' {
|
||||
take_while(|c: char| {
|
||||
match c {
|
||||
'a'..='z' | 'A'..='Z' | '_' | '0'..='9' => true,
|
||||
_ => false
|
||||
}
|
||||
take_while(|c: char| match c {
|
||||
'a'..='z' | 'A'..='Z' | '_' | '0'..='9' => true,
|
||||
_ => false,
|
||||
})(input)
|
||||
} else {
|
||||
Err(nom::Err::Error(make_error(
|
||||
|
|
@ -35,22 +42,13 @@ pub fn parse_column_name(input: &str) -> IResult<&str, String> {
|
|||
}
|
||||
|
||||
pub fn parse_db_type(input: &str) -> IResult<&str, DbType> {
|
||||
let (input, db_type) = alt(
|
||||
(
|
||||
tag("STRING")
|
||||
.map(|_| DbType::String),
|
||||
tag("INT")
|
||||
.map(|_| DbType::Int),
|
||||
tag("NUMBER")
|
||||
.map(|_| DbType::Number),
|
||||
tag("UUID")
|
||||
.map(|_| DbType::Uuid),
|
||||
delimited(tag("Option("), parse_db_type, tag(")"))
|
||||
.map(|ty| {
|
||||
DbType::Option(Box::new(ty))
|
||||
})
|
||||
)
|
||||
)(input)?;
|
||||
let (input, db_type) = alt((
|
||||
tag("STRING").map(|_| DbType::String),
|
||||
tag("INT").map(|_| DbType::Int),
|
||||
tag("NUMBER").map(|_| DbType::Number),
|
||||
tag("UUID").map(|_| DbType::Uuid),
|
||||
delimited(tag("Option("), parse_db_type, tag(")")).map(|ty| DbType::Option(Box::new(ty))),
|
||||
))(input)?;
|
||||
Ok((input, db_type))
|
||||
}
|
||||
|
||||
|
|
@ -122,10 +120,7 @@ mod tests {
|
|||
parse_identifier("_variable__Test").expect("should parse").1,
|
||||
"_variable__Test"
|
||||
);
|
||||
assert!(matches!(
|
||||
parse_identifier("123_variable__Test"),
|
||||
Err(_)
|
||||
));
|
||||
assert!(matches!(parse_identifier("123_variable__Test"), Err(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -139,8 +134,12 @@ mod tests {
|
|||
#[test]
|
||||
fn test_parse_nested_option_int_type() {
|
||||
assert_eq!(
|
||||
parse_db_type("Option(Option(Option(INT)))").expect("should parse").1,
|
||||
DbType::Option(Box::new(DbType::Option(Box::new(DbType::Option(Box::new(DbType::Int))))))
|
||||
parse_db_type("Option(Option(Option(INT)))")
|
||||
.expect("should parse")
|
||||
.1,
|
||||
DbType::Option(Box::new(DbType::Option(Box::new(DbType::Option(
|
||||
Box::new(DbType::Int)
|
||||
)))))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,8 +77,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_parse_create_no_quotes_table_name() {
|
||||
parse_create("CREATE TABLE Table1(id UUID PRIMARY KEY,column1 INT)")
|
||||
.expect("should parse");
|
||||
parse_create("CREATE TABLE Table1(id UUID PRIMARY KEY,column1 INT)").expect("should parse");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -91,8 +90,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_parse_create() {
|
||||
let (_, create) = parse_create("CREATE TABLE \"Table1\"( id UUID , column1 INT )")
|
||||
.expect("should parse");
|
||||
let (_, create) =
|
||||
parse_create("CREATE TABLE \"Table1\"( id UUID , column1 INT )").expect("should parse");
|
||||
assert!(matches!(create, RawQuerySyntax::CreateTable(_)));
|
||||
match create {
|
||||
RawQuerySyntax::CreateTable(schema) => {
|
||||
|
|
@ -114,11 +113,13 @@ mod tests {
|
|||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_parse_create_option() {
|
||||
let (_, create) = parse_create("CREATE TABLE games (id UUID PRIMARY KEY, name STRING, year Option(INT), price NUMBER)")
|
||||
.expect("should parse");
|
||||
let (_, create) = parse_create(
|
||||
"CREATE TABLE games (id UUID PRIMARY KEY, name STRING, year Option(INT), price NUMBER)",
|
||||
)
|
||||
.expect("should parse");
|
||||
assert!(matches!(create, RawQuerySyntax::CreateTable(_)));
|
||||
match create {
|
||||
RawQuerySyntax::CreateTable(schema) => {
|
||||
|
|
@ -139,16 +140,12 @@ mod tests {
|
|||
assert_eq!(column1_column.type_, DbType::String);
|
||||
|
||||
let column = schema.get_column(&"year".to_string());
|
||||
let Some(column) = column else {
|
||||
panic!()
|
||||
};
|
||||
let Some(column) = column else { panic!() };
|
||||
assert_eq!(column.column_name, "year".to_string());
|
||||
assert_eq!(column.type_, DbType::Option(Box::new(DbType::Int)));
|
||||
|
||||
let column = schema.get_column(&"price".to_string());
|
||||
let Some(column) = column else {
|
||||
panic!()
|
||||
};
|
||||
let Some(column) = column else { panic!() };
|
||||
assert_eq!(column.column_name, "price".to_string());
|
||||
assert_eq!(column.type_, DbType::Number);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,22 +29,19 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_parse_delete() {
|
||||
let (_, sntx) =
|
||||
parse_delete("DELETE FROM \"T1\" WHERE id = 1").expect("should parse");
|
||||
let (_, sntx) = parse_delete("DELETE FROM \"T1\" WHERE id = 1").expect("should parse");
|
||||
assert!(matches!(sntx, RawQuerySyntax::Delete(_, _)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_delete_with_spaces() {
|
||||
let (_, sntx) =
|
||||
parse_delete("DELETE FROM T1 WHERE id = 1").expect("should parse");
|
||||
let (_, sntx) = parse_delete("DELETE FROM T1 WHERE id = 1").expect("should parse");
|
||||
assert!(matches!(sntx, RawQuerySyntax::Delete(_, _)))
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_parse_delete_none() {
|
||||
let (_, sntx) =
|
||||
parse_delete("DELETE FROM games WHERE year = None").expect("should parse");
|
||||
let (_, sntx) = parse_delete("DELETE FROM games WHERE year = None").expect("should parse");
|
||||
if let RawQuerySyntax::Delete(tname, Some(Condition::Eq(column_name, lit))) = sntx {
|
||||
assert_eq!(tname, "games".to_string());
|
||||
assert_eq!(column_name, "year".to_string());
|
||||
|
|
|
|||
|
|
@ -68,10 +68,7 @@ mod tests {
|
|||
insertion_values,
|
||||
vec![
|
||||
("id".to_string(), Literal::Int(1)),
|
||||
(
|
||||
"data".to_string(),
|
||||
Literal::String("Text".to_string())
|
||||
)
|
||||
("data".to_string(), Literal::String("Text".to_string()))
|
||||
]
|
||||
);
|
||||
}
|
||||
|
|
@ -83,8 +80,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_parse_insert_with_spaces() {
|
||||
let sql =
|
||||
"INSERT INTO \"MyTable\" ( id, data ) VALUES ( 1, \"Text\" )";
|
||||
let sql = "INSERT INTO \"MyTable\" ( id, data ) VALUES ( 1, \"Text\" )";
|
||||
let operation = parse_insert(sql).expect("should parse");
|
||||
match operation {
|
||||
("", RawQuerySyntax::Insert(table_name, insertion_values)) => {
|
||||
|
|
@ -93,10 +89,7 @@ mod tests {
|
|||
insertion_values,
|
||||
vec![
|
||||
("id".to_string(), Literal::Int(1)),
|
||||
(
|
||||
"data".to_string(),
|
||||
Literal::String("Text".to_string())
|
||||
)
|
||||
("data".to_string(), Literal::String("Text".to_string()))
|
||||
]
|
||||
);
|
||||
}
|
||||
|
|
@ -117,18 +110,12 @@ mod tests {
|
|||
insertion_values,
|
||||
vec![
|
||||
("id".to_string(), Literal::Uuid(12345)),
|
||||
(
|
||||
"name".to_string(),
|
||||
Literal::String("Doom".to_string())
|
||||
),
|
||||
("name".to_string(), Literal::String("Doom".to_string())),
|
||||
(
|
||||
"year".to_string(),
|
||||
Literal::Some(Box::new(Literal::Int(1993)))
|
||||
),
|
||||
(
|
||||
"price".to_string(),
|
||||
Literal::Number(6.5)
|
||||
)
|
||||
("price".to_string(), Literal::Number(6.5))
|
||||
]
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
use nom::{
|
||||
branch::alt, bytes::complete::tag, character::complete::{char, digit1, none_of, u64}, combinator::opt, error::make_error, multi::many0, sequence::{delimited, pair, preceded}, IResult, Parser
|
||||
branch::alt,
|
||||
bytes::complete::tag,
|
||||
character::complete::{char, digit1, none_of, u64},
|
||||
combinator::opt,
|
||||
error::make_error,
|
||||
multi::many0,
|
||||
sequence::{delimited, pair, preceded},
|
||||
IResult, Parser,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
|
|
@ -13,7 +20,13 @@ pub enum Literal {
|
|||
}
|
||||
|
||||
pub fn parse_literal(input: &str) -> IResult<&str, Literal> {
|
||||
alt((parse_option, parse_string, parse_number, parse_int, parse_uuid))(input)
|
||||
alt((
|
||||
parse_option,
|
||||
parse_string,
|
||||
parse_number,
|
||||
parse_int,
|
||||
parse_uuid,
|
||||
))(input)
|
||||
}
|
||||
|
||||
pub fn parse_number(input: &str) -> IResult<&str, Literal> {
|
||||
|
|
@ -92,16 +105,16 @@ pub fn parse_string(input: &str) -> IResult<&str, Literal> {
|
|||
}
|
||||
|
||||
pub fn parse_uuid(input: &str) -> IResult<&str, Literal> {
|
||||
let (input, value) = pair(char('u'), u64)(input)
|
||||
.map(|(input, (_, v))| (input, Literal::Uuid(v)))?;
|
||||
let (input, value) =
|
||||
pair(char('u'), u64)(input).map(|(input, (_, v))| (input, Literal::Uuid(v)))?;
|
||||
Ok((input, value))
|
||||
}
|
||||
|
||||
pub fn parse_option(input: &str) -> IResult<&str, Literal> {
|
||||
let (input, inner) = alt((tag("None")
|
||||
.map(|_| Literal::None), delimited(tag("Some("), parse_literal, tag(")")).map(|v| {
|
||||
Literal::Some(Box::new(v))
|
||||
})))(input)?;
|
||||
let (input, inner) = alt((
|
||||
tag("None").map(|_| Literal::None),
|
||||
delimited(tag("Some("), parse_literal, tag(")")).map(|v| Literal::Some(Box::new(v))),
|
||||
))(input)?;
|
||||
Ok((input, inner))
|
||||
}
|
||||
|
||||
|
|
@ -114,24 +127,15 @@ mod tests {
|
|||
fn test_string_parser() {
|
||||
assert_eq!(
|
||||
parse_string(r#""simple""#),
|
||||
Ok((
|
||||
"",
|
||||
Literal::String(String::from("simple"))
|
||||
))
|
||||
Ok(("", Literal::String(String::from("simple"))))
|
||||
);
|
||||
assert_eq!(
|
||||
parse_string(r#""\"\t\r\n\\""#),
|
||||
Ok((
|
||||
"",
|
||||
Literal::String(String::from("\"\t\r\n\\"))
|
||||
))
|
||||
Ok(("", Literal::String(String::from("\"\t\r\n\\"))))
|
||||
);
|
||||
assert_eq!(
|
||||
parse_string(r#""name is \"John\".""#),
|
||||
Ok((
|
||||
"",
|
||||
Literal::String(String::from("name is \"John\"."))
|
||||
))
|
||||
Ok(("", Literal::String(String::from("name is \"John\"."))))
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -147,13 +151,11 @@ mod tests {
|
|||
|
||||
let (_, _) = parse_literal("\"STRING\"").expect("should parse");
|
||||
let (input, value) =
|
||||
parse_literal("\"abcdefghkjklmnopqrstuvwxyz!@#$%^&*()_+ \"").expect("should parse");
|
||||
parse_literal("\"abcdefghkjklmnopqrstuvwxyz!@#$%^&*()_+ \"").expect("should parse");
|
||||
assert_eq!(input, "");
|
||||
assert_eq!(
|
||||
value,
|
||||
Literal::String(
|
||||
"abcdefghkjklmnopqrstuvwxyz!@#$%^&*()_+ ".to_string()
|
||||
)
|
||||
Literal::String("abcdefghkjklmnopqrstuvwxyz!@#$%^&*()_+ ".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -192,18 +194,12 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_parse_int() {
|
||||
assert_eq!(
|
||||
parse_literal("5134616"),
|
||||
Ok(("", Literal::Int(5134616)))
|
||||
);
|
||||
assert_eq!(parse_literal("5134616"), Ok(("", Literal::Int(5134616))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_uuid() {
|
||||
assert_eq!(
|
||||
parse_uuid("u131515"),
|
||||
Ok(("", Literal::Uuid(131515)))
|
||||
)
|
||||
assert_eq!(parse_uuid("u131515"), Ok(("", Literal::Uuid(131515))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -214,7 +210,10 @@ mod tests {
|
|||
);
|
||||
assert_eq!(
|
||||
parse_option("Some(Some(3))"),
|
||||
Ok(("", Literal::Some(Box::new(Literal::Some(Box::new(Literal::Int(3)))))))
|
||||
Ok((
|
||||
"",
|
||||
Literal::Some(Box::new(Literal::Some(Box::new(Literal::Int(3)))))
|
||||
))
|
||||
);
|
||||
assert_eq!(
|
||||
parse_option("Some(None)"),
|
||||
|
|
|
|||
|
|
@ -42,7 +42,9 @@ pub fn try_parse_column_selection(input: &str) -> IResult<&str, ColumnSelection>
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::parsing::{
|
||||
common::{parse_column_name, parse_table_name}, literal::Literal, select::parse_select
|
||||
common::{parse_column_name, parse_table_name},
|
||||
literal::Literal,
|
||||
select::parse_select,
|
||||
};
|
||||
use crate::syntax::{ColumnSelection, RawQuerySyntax};
|
||||
|
||||
|
|
@ -137,7 +139,7 @@ mod tests {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_parse_select_option_none() {
|
||||
use crate::syntax::Condition;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue