Parsing and validation for Option
Add option type and option value parsers value->literal in parser, implement Option literal
This commit is contained in:
parent
de8c6164cf
commit
6245dba4f0
8 changed files with 322 additions and 109 deletions
|
|
@ -1,16 +1,10 @@
|
|||
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,
|
||||
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 super::literal::parse_db_value;
|
||||
use crate::syntax::Condition;
|
||||
use super::literal::parse_literal;
|
||||
|
||||
pub fn parse_table_name(input: &str) -> IResult<&str, &str> {
|
||||
alt((
|
||||
|
|
@ -38,19 +32,22 @@ pub fn parse_column_name(input: &str) -> IResult<&str, String> {
|
|||
}
|
||||
|
||||
pub fn parse_db_type(input: &str) -> IResult<&str, DbType> {
|
||||
let (input, type_name) = alt((tag("STRING"), tag("INT"), tag("NUMBER"), tag("UUID")))(input)?;
|
||||
let db_type = match type_name {
|
||||
"STRING" => DbType::String,
|
||||
"INT" => DbType::Int,
|
||||
"UUID" => DbType::Uuid,
|
||||
"NUMBER" => DbType::Number,
|
||||
_ => {
|
||||
return Err(nom::Err::Failure(make_error(
|
||||
input,
|
||||
nom::error::ErrorKind::IsNot,
|
||||
)))
|
||||
}
|
||||
};
|
||||
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))
|
||||
}
|
||||
|
||||
|
|
@ -70,8 +67,8 @@ fn parse_equality(input: &str) -> IResult<&str, Condition> {
|
|||
let (input, _) = multispace0(input)?;
|
||||
let (input, _) = char('=')(input)?;
|
||||
let (input, _) = multispace0(input)?;
|
||||
let (input, db_value) = parse_db_value(input)?;
|
||||
Ok((input, Condition::Eq(column_name, db_value)))
|
||||
let (input, lit) = parse_literal(input)?;
|
||||
Ok((input, Condition::Eq(column_name, lit)))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
@ -79,15 +76,15 @@ mod tests {
|
|||
use minisql::type_system::DbType;
|
||||
|
||||
use crate::parsing::common::{parse_db_type, parse_equality, parse_identifier};
|
||||
use crate::parsing::literal::Literal;
|
||||
use crate::syntax::Condition;
|
||||
|
||||
#[test]
|
||||
fn test_parse_equality() {
|
||||
use minisql::type_system::Value;
|
||||
match parse_equality("id = 1") {
|
||||
Ok(("", Condition::Eq(column_name, value))) => {
|
||||
assert!(column_name.eq("id"));
|
||||
assert_eq!(value, Value::Int(1))
|
||||
assert_eq!(value, Literal::Int(1))
|
||||
}
|
||||
_ => {
|
||||
panic!("should parse");
|
||||
|
|
@ -127,4 +124,20 @@ mod tests {
|
|||
Err(_)
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_option_string_type() {
|
||||
assert_eq!(
|
||||
parse_db_type("Option(STRING)").expect("should parse").1,
|
||||
DbType::Option(Box::new(DbType::String))
|
||||
);
|
||||
}
|
||||
|
||||
#[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))))))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,8 @@ fn parse_column_definition(input: &str) -> IResult<&str, ColumnSchema> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use minisql::type_system::DbType;
|
||||
|
||||
use crate::parsing::create::parse_create;
|
||||
use crate::syntax::RawQuerySyntax;
|
||||
|
||||
|
|
@ -112,4 +114,45 @@ 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");
|
||||
assert!(matches!(create, RawQuerySyntax::CreateTable(_)));
|
||||
match create {
|
||||
RawQuerySyntax::CreateTable(schema) => {
|
||||
assert_eq!(schema.table_name, "games");
|
||||
assert_eq!(schema.number_of_columns(), 4);
|
||||
|
||||
let result_id = schema.get_column(&"id".to_string());
|
||||
assert!(matches!(result_id, Some(_)));
|
||||
let Some(id_column) = result_id else { panic!() };
|
||||
assert_eq!(id_column.column_name, "id".to_string());
|
||||
|
||||
let result_column1 = schema.get_column(&"name".to_string());
|
||||
assert!(matches!(result_column1, Some(_)));
|
||||
let Some(column1_column) = result_column1 else {
|
||||
panic!()
|
||||
};
|
||||
assert_eq!(column1_column.column_name, "name".to_string());
|
||||
assert_eq!(column1_column.type_, DbType::String);
|
||||
|
||||
let column = schema.get_column(&"year".to_string());
|
||||
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!()
|
||||
};
|
||||
assert_eq!(column.column_name, "price".to_string());
|
||||
assert_eq!(column.type_, DbType::Number);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use nom::{
|
||||
bytes::complete::tag,
|
||||
character::complete::{char, multispace0, multispace1},
|
||||
character::complete::{multispace0, multispace1},
|
||||
IResult,
|
||||
};
|
||||
|
||||
|
|
@ -24,19 +24,33 @@ pub fn parse_delete(input: &str) -> IResult<&str, RawQuerySyntax> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::parsing::delete::parse_delete;
|
||||
use crate::syntax::RawQuerySyntax;
|
||||
use crate::parsing::literal::Literal;
|
||||
use crate::syntax::{Condition, RawQuerySyntax};
|
||||
|
||||
#[test]
|
||||
fn test_parse_delete() {
|
||||
let (_, operation) =
|
||||
let (_, sntx) =
|
||||
parse_delete("DELETE FROM \"T1\" WHERE id = 1").expect("should parse");
|
||||
assert!(matches!(operation, RawQuerySyntax::Delete(_, _)))
|
||||
assert!(matches!(sntx, RawQuerySyntax::Delete(_, _)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_delete_with_spaces() {
|
||||
let (_, operation) =
|
||||
let (_, sntx) =
|
||||
parse_delete("DELETE FROM T1 WHERE id = 1").expect("should parse");
|
||||
assert!(matches!(operation, RawQuerySyntax::Delete(_, _)))
|
||||
assert!(matches!(sntx, RawQuerySyntax::Delete(_, _)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_delete_none() {
|
||||
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());
|
||||
assert_eq!(lit, Literal::None)
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
use super::{
|
||||
common::{parse_identifier, parse_table_name},
|
||||
literal::parse_db_value,
|
||||
literal::{parse_literal, Literal},
|
||||
};
|
||||
use crate::syntax::RawQuerySyntax;
|
||||
use minisql::type_system::Value;
|
||||
use nom::{
|
||||
bytes::complete::tag,
|
||||
character::complete::{char, multispace0, multispace1},
|
||||
|
|
@ -49,16 +48,14 @@ pub fn parse_columns(input: &str) -> IResult<&str, Vec<String>> {
|
|||
)(input)
|
||||
}
|
||||
|
||||
pub fn parse_values(input: &str) -> IResult<&str, Vec<Value>> {
|
||||
separated_list0(terminated(char(','), multispace0), parse_db_value)(input)
|
||||
pub fn parse_values(input: &str) -> IResult<&str, Vec<Literal>> {
|
||||
separated_list0(terminated(char(','), multispace0), parse_literal)(input)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use minisql::type_system::Value;
|
||||
|
||||
use super::parse_insert;
|
||||
use crate::syntax::RawQuerySyntax;
|
||||
use crate::{parsing::literal::Literal, syntax::RawQuerySyntax};
|
||||
|
||||
#[test]
|
||||
fn test_parse_insert() {
|
||||
|
|
@ -70,10 +67,10 @@ mod tests {
|
|||
assert_eq!(
|
||||
insertion_values,
|
||||
vec![
|
||||
("id".to_string(), Value::Int(1)),
|
||||
("id".to_string(), Literal::Int(1)),
|
||||
(
|
||||
"data".to_string(),
|
||||
Value::String("Text".to_string())
|
||||
Literal::String("Text".to_string())
|
||||
)
|
||||
]
|
||||
);
|
||||
|
|
@ -95,10 +92,10 @@ mod tests {
|
|||
assert_eq!(
|
||||
insertion_values,
|
||||
vec![
|
||||
("id".to_string(), Value::Int(1)),
|
||||
("id".to_string(), Literal::Int(1)),
|
||||
(
|
||||
"data".to_string(),
|
||||
Value::String("Text".to_string())
|
||||
Literal::String("Text".to_string())
|
||||
)
|
||||
]
|
||||
);
|
||||
|
|
@ -108,4 +105,36 @@ mod tests {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_insert_option() {
|
||||
let sql = r#"INSERT INTO games (id, name, year, price) VALUES (u12345, "Doom", Some(1993), 6.5);"#;
|
||||
let syntax = parse_insert(sql).expect("should parse");
|
||||
match syntax {
|
||||
(";", RawQuerySyntax::Insert(table_name, insertion_values)) => {
|
||||
assert_eq!(table_name, "games");
|
||||
assert_eq!(
|
||||
insertion_values,
|
||||
vec![
|
||||
("id".to_string(), Literal::Uuid(12345)),
|
||||
(
|
||||
"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)
|
||||
)
|
||||
]
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,23 @@
|
|||
use minisql::type_system::Value;
|
||||
use minisql::type_system::DbType;
|
||||
use nom::{
|
||||
branch::alt,
|
||||
character::complete::{char, digit1, none_of, u64},
|
||||
combinator::opt,
|
||||
error::make_error,
|
||||
multi::many0,
|
||||
sequence::{delimited, pair, preceded},
|
||||
IResult,
|
||||
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
|
||||
};
|
||||
|
||||
pub fn parse_db_value(input: &str) -> IResult<&str, Value> {
|
||||
alt((parse_string, parse_number, parse_int, parse_uuid))(input)
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Literal {
|
||||
Number(f64),
|
||||
String(String),
|
||||
Int(u64),
|
||||
Uuid(u64),
|
||||
Some(Box<Literal>),
|
||||
None,
|
||||
}
|
||||
|
||||
pub fn parse_number(input: &str) -> IResult<&str, Value> {
|
||||
pub fn parse_literal(input: &str) -> IResult<&str, Literal> {
|
||||
alt((parse_option, parse_string, parse_number, parse_int, parse_uuid))(input)
|
||||
}
|
||||
|
||||
pub fn parse_number(input: &str) -> IResult<&str, Literal> {
|
||||
// Parse the integer part
|
||||
let (input, (sign, digits)) = pair(opt(char('-')), digit1)(input)?;
|
||||
|
||||
|
|
@ -28,19 +32,19 @@ pub fn parse_number(input: &str) -> IResult<&str, Value> {
|
|||
let value = combined_parts
|
||||
.parse::<f64>()
|
||||
.map_err(|_| nom::Err::Failure(make_error(input, nom::error::ErrorKind::Fail)))?;
|
||||
Ok((input, Value::Number(value)))
|
||||
Ok((input, Literal::Number(value)))
|
||||
}
|
||||
None => {
|
||||
let value = format!("{}{}", sign.unwrap_or('+'), digits)
|
||||
.parse::<u64>()
|
||||
.map_err(|_| nom::Err::Failure(make_error(input, nom::error::ErrorKind::Fail)))?;
|
||||
Ok((input, Value::Int(value)))
|
||||
Ok((input, Literal::Int(value)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_int(input: &str) -> IResult<&str, Value> {
|
||||
u64(input).map(|(input, v)| (input, Value::Int(v)))
|
||||
pub fn parse_int(input: &str) -> IResult<&str, Literal> {
|
||||
u64(input).map(|(input, v)| (input, Literal::Int(v)))
|
||||
}
|
||||
|
||||
fn escape_tab(input: &str) -> IResult<&str, char> {
|
||||
|
|
@ -67,7 +71,7 @@ fn escape_doublequote(input: &str) -> IResult<&str, char> {
|
|||
preceded(char('\\'), char('"'))(input)
|
||||
}
|
||||
|
||||
pub fn parse_string(input: &str) -> IResult<&str, Value> {
|
||||
pub fn parse_string(input: &str) -> IResult<&str, Literal> {
|
||||
// Parse the content inside the double quotes
|
||||
let (input, content) = delimited(
|
||||
char('"'),
|
||||
|
|
@ -85,19 +89,27 @@ pub fn parse_string(input: &str) -> IResult<&str, Value> {
|
|||
// Combine the characters into a string
|
||||
let value: String = content.into_iter().collect();
|
||||
|
||||
Ok((input, Value::String(value)))
|
||||
Ok((input, Literal::String(value)))
|
||||
}
|
||||
|
||||
pub fn parse_uuid(input: &str) -> IResult<&str, Value> {
|
||||
pub fn parse_uuid(input: &str) -> IResult<&str, Literal> {
|
||||
let (input, value) = pair(char('u'), u64)(input)
|
||||
.map(|(input, (_, v))| (input, Value::Uuid(v)))?;
|
||||
.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)?;
|
||||
Ok((input, inner))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::parsing::literal::{parse_db_value, parse_string, parse_uuid};
|
||||
use minisql::type_system::Value;
|
||||
use crate::parsing::literal::{parse_literal, parse_option, parse_string, parse_uuid, Literal};
|
||||
use minisql::type_system::DbType;
|
||||
|
||||
#[test]
|
||||
fn test_string_parser() {
|
||||
|
|
@ -105,42 +117,42 @@ mod tests {
|
|||
parse_string(r#""simple""#),
|
||||
Ok((
|
||||
"",
|
||||
Value::String(String::from("simple"))
|
||||
Literal::String(String::from("simple"))
|
||||
))
|
||||
);
|
||||
assert_eq!(
|
||||
parse_string(r#""\"\t\r\n\\""#),
|
||||
Ok((
|
||||
"",
|
||||
Value::String(String::from("\"\t\r\n\\"))
|
||||
Literal::String(String::from("\"\t\r\n\\"))
|
||||
))
|
||||
);
|
||||
assert_eq!(
|
||||
parse_string(r#""name is \"John\".""#),
|
||||
Ok((
|
||||
"",
|
||||
Value::String(String::from("name is \"John\"."))
|
||||
Literal::String(String::from("name is \"John\"."))
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_db_value() {
|
||||
let (input, value) = parse_db_value("5").expect("should parse");
|
||||
let (input, value) = parse_literal("5").expect("should parse");
|
||||
assert_eq!(input, "");
|
||||
assert_eq!(value, Value::Int(5));
|
||||
assert_eq!(value, Literal::Int(5));
|
||||
|
||||
let (input, value) = parse_db_value("5.5").expect("should parse");
|
||||
let (input, value) = parse_literal("5.5").expect("should parse");
|
||||
assert_eq!(input, "");
|
||||
assert_eq!(value, Value::Number(5.5));
|
||||
assert_eq!(value, Literal::Number(5.5));
|
||||
|
||||
let (_, _) = parse_db_value("\"STRING\"").expect("should parse");
|
||||
let (_, _) = parse_literal("\"STRING\"").expect("should parse");
|
||||
let (input, value) =
|
||||
parse_db_value("\"abcdefghkjklmnopqrstuvwxyz!@#$%^&*()_+ \"").expect("should parse");
|
||||
parse_literal("\"abcdefghkjklmnopqrstuvwxyz!@#$%^&*()_+ \"").expect("should parse");
|
||||
assert_eq!(input, "");
|
||||
assert_eq!(
|
||||
value,
|
||||
Value::String(
|
||||
Literal::String(
|
||||
"abcdefghkjklmnopqrstuvwxyz!@#$%^&*()_+ ".to_string()
|
||||
)
|
||||
);
|
||||
|
|
@ -149,41 +161,41 @@ mod tests {
|
|||
#[test]
|
||||
fn test_parse_positive_float() {
|
||||
assert_eq!(
|
||||
parse_db_value("23.213313"),
|
||||
Ok(("", Value::Number(23.213313)))
|
||||
parse_literal("23.213313"),
|
||||
Ok(("", Literal::Number(23.213313)))
|
||||
);
|
||||
assert_eq!(
|
||||
parse_db_value("2241.9734"),
|
||||
Ok(("", Value::Number(2241.9734)))
|
||||
parse_literal("2241.9734"),
|
||||
Ok(("", Literal::Number(2241.9734)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_negative_float() {
|
||||
assert_eq!(
|
||||
parse_db_value("-9241.873654"),
|
||||
Ok(("", Value::Number(-9241.873654)))
|
||||
parse_literal("-9241.873654"),
|
||||
Ok(("", Literal::Number(-9241.873654)))
|
||||
);
|
||||
assert_eq!(
|
||||
parse_db_value("-62625.0"),
|
||||
Ok(("", Value::Number(-62625.0)))
|
||||
parse_literal("-62625.0"),
|
||||
Ok(("", Literal::Number(-62625.0)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_float_between_0_and_1() {
|
||||
assert_eq!(
|
||||
parse_db_value("0.873654"),
|
||||
Ok(("", Value::Number(0.873654)))
|
||||
parse_literal("0.873654"),
|
||||
Ok(("", Literal::Number(0.873654)))
|
||||
);
|
||||
assert_eq!(parse_db_value("0.62625"), Ok(("", Value::Number(0.62625))));
|
||||
assert_eq!(parse_literal("0.62625"), Ok(("", Literal::Number(0.62625))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_int() {
|
||||
assert_eq!(
|
||||
parse_db_value("5134616"),
|
||||
Ok(("", Value::Int(5134616)))
|
||||
parse_literal("5134616"),
|
||||
Ok(("", Literal::Int(5134616)))
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -191,7 +203,23 @@ mod tests {
|
|||
fn test_parse_uuid() {
|
||||
assert_eq!(
|
||||
parse_uuid("u131515"),
|
||||
Ok(("", Value::Uuid(131515)))
|
||||
Ok(("", Literal::Uuid(131515)))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_option_int() {
|
||||
assert_eq!(
|
||||
parse_option("Some(2)"),
|
||||
Ok(("", Literal::Some(Box::new(Literal::Int(2)))))
|
||||
);
|
||||
assert_eq!(
|
||||
parse_option("Some(Some(3))"),
|
||||
Ok(("", Literal::Some(Box::new(Literal::Some(Box::new(Literal::Int(3)))))))
|
||||
);
|
||||
assert_eq!(
|
||||
parse_option("Some(None)"),
|
||||
Ok(("", Literal::Some(Box::new(Literal::None))))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,8 +42,7 @@ 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},
|
||||
select::parse_select,
|
||||
common::{parse_column_name, parse_table_name}, literal::Literal, select::parse_select
|
||||
};
|
||||
use crate::syntax::{ColumnSelection, RawQuerySyntax};
|
||||
|
||||
|
|
@ -116,4 +115,49 @@ mod tests {
|
|||
}
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn test_parse_select_option() {
|
||||
use crate::syntax::Condition;
|
||||
let sql = "SELECT * FROM games WHERE year = Some(2006)";
|
||||
let operation = parse_select(sql).expect("should parse");
|
||||
match operation {
|
||||
("", RawQuerySyntax::Select(table_name, column_selection, maybe_condition)) => {
|
||||
assert_eq!(table_name, "games");
|
||||
assert!(matches!(column_selection, ColumnSelection::All));
|
||||
if let Some(Condition::Eq(left, right)) = maybe_condition {
|
||||
assert_eq!(left, "year".to_string());
|
||||
assert_eq!(right, Literal::Some(Box::new(Literal::Int(2006))))
|
||||
} else {
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
(input, _) => {
|
||||
println!("Input to be parsed: {}", input);
|
||||
panic!("expected select operation")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_select_option_none() {
|
||||
use crate::syntax::Condition;
|
||||
let sql = "SELECT * FROM games WHERE year = None";
|
||||
let operation = parse_select(sql).expect("should parse");
|
||||
match operation {
|
||||
("", RawQuerySyntax::Select(table_name, column_selection, maybe_condition)) => {
|
||||
assert_eq!(table_name, "games");
|
||||
assert!(matches!(column_selection, ColumnSelection::All));
|
||||
if let Some(Condition::Eq(left, right)) = maybe_condition {
|
||||
assert_eq!(left, "year".to_string());
|
||||
assert_eq!(right, Literal::None)
|
||||
} else {
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
(input, _) => {
|
||||
println!("Input to be parsed: {}", input);
|
||||
panic!("expected select operation")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue