Use RawQuerySyntax for parsing
This commit is contained in:
parent
562e732138
commit
9771a89716
10 changed files with 65 additions and 62 deletions
|
|
@ -2,7 +2,7 @@ use crate::error::Error;
|
||||||
use crate::internals::row::{ColumnPosition, Row};
|
use crate::internals::row::{ColumnPosition, Row};
|
||||||
use crate::schema::{TableName, TableSchema};
|
use crate::schema::{TableName, TableSchema};
|
||||||
use crate::internals::table::Table;
|
use crate::internals::table::Table;
|
||||||
use crate::operation::{ColumnSelection, Condition, Operation, OperationForInterpreter, ConditionForInterpreter, ColumnSelectionForInterpreter};
|
use crate::operation::{ColumnSelection, Condition, Operation, OperationForInterpreter, ConditionForInterpreter};
|
||||||
use crate::result::DbResult;
|
use crate::result::DbResult;
|
||||||
use crate::type_system::{DbType, IndexableValue, Value};
|
use crate::type_system::{DbType, IndexableValue, Value};
|
||||||
use bimap::BiMap;
|
use bimap::BiMap;
|
||||||
|
|
@ -27,6 +27,8 @@ pub enum Response<'a> {
|
||||||
IndexCreated,
|
IndexCreated,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type DbSchema<'a> = Vec<(TableName, TablePosition, &'a TableSchema)>;
|
||||||
|
|
||||||
impl std::fmt::Debug for Response<'_> {
|
impl std::fmt::Debug for Response<'_> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||||
use Response::*;
|
use Response::*;
|
||||||
|
|
@ -56,13 +58,13 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO: return a reference to avoid allocations
|
/// TODO: return a reference to avoid allocations
|
||||||
pub fn metadata<'a>(&'a self) -> Vec<(String, &'a TableSchema)> {
|
pub fn db_schema<'a>(&'a self) -> DbSchema {
|
||||||
let mut m = Vec::new();
|
let mut schema: DbSchema = Vec::new();
|
||||||
for (name, pos) in &self.table_name_position_mapping {
|
for (table_name, &table_position) in &self.table_name_position_mapping {
|
||||||
let table_schema = self.tables.get(*pos).unwrap().schema();
|
let table_schema = self.tables[table_position].schema();
|
||||||
m.push((name.clone(), table_schema));
|
schema.push((table_name.clone(), table_position, table_schema));
|
||||||
}
|
}
|
||||||
m
|
schema
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Get rid of this
|
// TODO: Get rid of this
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use minisql::{operation::Operation, schema::TableSchema};
|
use minisql::{operation::OperationForInterpreter, interpreter::DbSchema};
|
||||||
use crate::syntax::RawQuerySyntax;
|
use crate::syntax::RawQuerySyntax;
|
||||||
use nom::{branch::alt, multi::many0, IResult};
|
use nom::{branch::alt, multi::many0, IResult};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
@ -13,7 +13,7 @@ pub enum Error {
|
||||||
ValidationError(#[from] ValidationError)
|
ValidationError(#[from] ValidationError)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_statement<'a>(input: &'a str) -> IResult<&str, Operation> {
|
pub fn parse_statement<'a>(input: &'a str) -> IResult<&str, RawQuerySyntax> {
|
||||||
alt((
|
alt((
|
||||||
parse_insert,
|
parse_insert,
|
||||||
parse_create,
|
parse_create,
|
||||||
|
|
@ -25,20 +25,17 @@ pub fn parse_statement<'a>(input: &'a str) -> IResult<&str, Operation> {
|
||||||
))(input)
|
))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_statements<'a>(input: &'a str) -> IResult<&str, Vec<Operation>> {
|
pub fn parse_statements<'a>(input: &'a str) -> IResult<&str, Vec<RawQuerySyntax>> {
|
||||||
many0(parse_statement)(input)
|
many0(parse_statement)(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_and_validate(query: String, db_metadata: &Vec<(String, &TableSchema)>) -> Result<Operation, Error> {
|
pub fn parse_and_validate(query: String, db_schema: &DbSchema) -> Result<OperationForInterpreter, Error> {
|
||||||
let (_, op) = parse_statement(query.as_str())
|
let (_, op) = parse_statement(query.as_str())
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
Error::ParsingError(err.to_string())
|
Error::ParsingError(err.to_string())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// TODO
|
Ok(validate_operation(op, db_schema)?)
|
||||||
// validate_operation(&op, db_metadata)?;
|
|
||||||
todo!();
|
|
||||||
Ok(op)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[test]
|
// #[test]
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,9 @@ use nom::{
|
||||||
bytes::complete::tag,
|
bytes::complete::tag,
|
||||||
IResult, branch::alt,
|
IResult, branch::alt,
|
||||||
};
|
};
|
||||||
use minisql::{operation::Condition, type_system::DbType};
|
use minisql::type_system::DbType;
|
||||||
|
|
||||||
|
use crate::syntax::Condition;
|
||||||
use super::literal::parse_db_value;
|
use super::literal::parse_db_value;
|
||||||
|
|
||||||
pub fn parse_table_name(input: &str) -> IResult<&str, &str> {
|
pub fn parse_table_name(input: &str) -> IResult<&str, &str> {
|
||||||
|
|
@ -67,7 +68,9 @@ fn parse_equality(input: &str) -> IResult<&str, Condition> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use minisql::{operation::Condition, type_system::DbType};
|
use minisql::type_system::DbType;
|
||||||
|
|
||||||
|
use crate::syntax::Condition;
|
||||||
use crate::parsing::common::{parse_db_type, parse_equality};
|
use crate::parsing::common::{parse_db_type, parse_equality};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use minisql::{operation::Operation, schema::{ColumnName, TableSchema}, type_system::DbType};
|
use minisql::{schema::{ColumnName, TableSchema}, type_system::DbType};
|
||||||
use nom::{
|
use nom::{
|
||||||
bytes::complete::tag,
|
bytes::complete::tag,
|
||||||
character::complete::{char, multispace0, multispace1},
|
character::complete::{char, multispace0, multispace1},
|
||||||
|
|
@ -8,8 +8,9 @@ use nom::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::common::{parse_table_name, parse_identifier, parse_db_type};
|
use super::common::{parse_table_name, parse_identifier, parse_db_type};
|
||||||
|
use crate::syntax::RawQuerySyntax;
|
||||||
|
|
||||||
pub fn parse_create(input: &str) -> IResult<&str, Operation> {
|
pub fn parse_create(input: &str) -> IResult<&str, RawQuerySyntax> {
|
||||||
let (input, _) = tag("CREATE")(input)?;
|
let (input, _) = tag("CREATE")(input)?;
|
||||||
let (input, _) = multispace1(input)?;
|
let (input, _) = multispace1(input)?;
|
||||||
let (input, _) = tag("TABLE")(input)?;
|
let (input, _) = tag("TABLE")(input)?;
|
||||||
|
|
@ -41,7 +42,7 @@ pub fn parse_create(input: &str) -> IResult<&str, Operation> {
|
||||||
);
|
);
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
Operation::CreateTable(table_name.to_string(), schema),
|
RawQuerySyntax::CreateTable(table_name.to_string(), schema),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -68,8 +69,8 @@ pub fn parse_column_definition(input: &str) -> IResult<&str, (ColumnName, DbType
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use minisql::operation::Operation;
|
|
||||||
use crate::parsing::create::parse_create;
|
use crate::parsing::create::parse_create;
|
||||||
|
use crate::syntax::RawQuerySyntax;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_create_no_spaces() {
|
fn test_parse_create_no_spaces() {
|
||||||
|
|
@ -94,9 +95,9 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_create() {
|
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, Operation::CreateTable(_ ,_)));
|
assert!(matches!(create, RawQuerySyntax::CreateTable(_ ,_)));
|
||||||
match create {
|
match create {
|
||||||
Operation::CreateTable(name, schema) => {
|
RawQuerySyntax::CreateTable(name, schema) => {
|
||||||
assert_eq!(name, "Table1");
|
assert_eq!(name, "Table1");
|
||||||
assert_eq!(schema.number_of_columns(), 2);
|
assert_eq!(schema.number_of_columns(), 2);
|
||||||
assert_eq!(schema.column_position_from_column_name(&"id".to_string()).unwrap(), 0);
|
assert_eq!(schema.column_position_from_column_name(&"id".to_string()).unwrap(), 0);
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
use minisql::operation::Operation;
|
|
||||||
use nom::{
|
use nom::{
|
||||||
bytes::complete::tag,
|
bytes::complete::tag,
|
||||||
character::complete::{char, multispace0, multispace1},
|
character::complete::{char, multispace0, multispace1},
|
||||||
IResult,
|
IResult,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::syntax::RawQuerySyntax;
|
||||||
use super::common::{parse_table_name, parse_condition};
|
use super::common::{parse_table_name, parse_condition};
|
||||||
|
|
||||||
pub fn parse_delete(input: &str) -> IResult<&str, Operation> {
|
pub fn parse_delete(input: &str) -> IResult<&str, RawQuerySyntax> {
|
||||||
let (input, _) = tag("DELETE")(input)?;
|
let (input, _) = tag("DELETE")(input)?;
|
||||||
let (input, _) = multispace1(input)?;
|
let (input, _) = multispace1(input)?;
|
||||||
let (input, _) = tag("FROM")(input)?;
|
let (input, _) = tag("FROM")(input)?;
|
||||||
|
|
@ -19,19 +19,19 @@ pub fn parse_delete(input: &str) -> IResult<&str, Operation> {
|
||||||
let (input, _) = char(';')(input)?;
|
let (input, _) = char(';')(input)?;
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
Operation::Delete(table_name.to_string(), condition),
|
RawQuerySyntax::Delete(table_name.to_string(), condition),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use minisql::operation::Operation;
|
use crate::syntax::RawQuerySyntax;
|
||||||
use crate::parsing::delete::parse_delete;
|
use crate::parsing::delete::parse_delete;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_delete() {
|
fn test_parse_delete() {
|
||||||
let (_, operation) = parse_delete("DELETE FROM \"T1\" WHERE id = 1 ;").expect("should parse");
|
let (_, operation) = parse_delete("DELETE FROM \"T1\" WHERE id = 1 ;").expect("should parse");
|
||||||
assert!(matches!(operation, Operation::Delete(_, _)))
|
assert!(matches!(operation, RawQuerySyntax::Delete(_, _)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add test with condition
|
// TODO: add test with condition
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use minisql::operation::Operation;
|
use crate::syntax::RawQuerySyntax;
|
||||||
use nom::{
|
use nom::{
|
||||||
bytes::complete::tag,
|
bytes::complete::tag,
|
||||||
character::complete::{char, multispace0, multispace1},
|
character::complete::{char, multispace0, multispace1},
|
||||||
|
|
@ -7,7 +7,7 @@ use nom::{
|
||||||
|
|
||||||
use super::common::{parse_identifier, parse_table_name};
|
use super::common::{parse_identifier, parse_table_name};
|
||||||
|
|
||||||
pub fn parse_create_index(input: &str) -> IResult<&str, Operation> {
|
pub fn parse_create_index(input: &str) -> IResult<&str, RawQuerySyntax> {
|
||||||
let (input, _) = tag("CREATE")(input)?;
|
let (input, _) = tag("CREATE")(input)?;
|
||||||
let unique = |input| -> IResult<&str, bool> {
|
let unique = |input| -> IResult<&str, bool> {
|
||||||
let (input, _) = multispace1(input)?;
|
let (input, _) = multispace1(input)?;
|
||||||
|
|
@ -31,23 +31,23 @@ pub fn parse_create_index(input: &str) -> IResult<&str, Operation> {
|
||||||
let (input, _) = char(')')(input)?;
|
let (input, _) = char(')')(input)?;
|
||||||
let (input, _) = multispace0(input)?;
|
let (input, _) = multispace0(input)?;
|
||||||
let (input, _) = char(';')(input)?;
|
let (input, _) = char(';')(input)?;
|
||||||
let operation = Operation::CreateIndex(table_name.to_string(), column_name.to_string());
|
let operation = RawQuerySyntax::CreateIndex(table_name.to_string(), column_name.to_string());
|
||||||
Ok((input, operation))
|
Ok((input, operation))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use minisql::operation::Operation;
|
use crate::syntax::RawQuerySyntax;
|
||||||
use crate::parsing::index::parse_create_index;
|
use crate::parsing::index::parse_create_index;
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_create_index() {
|
fn test_create_index() {
|
||||||
let (_, operation) = parse_create_index("CREATE UNIQUE INDEX idxcontactsemail ON \"contacts\" (email);").expect("should parse");
|
let (_, syntax) = parse_create_index("CREATE UNIQUE INDEX idxcontactsemail ON \"contacts\" (email);").expect("should parse");
|
||||||
assert!(matches!(operation, Operation::CreateIndex(_, _)));
|
assert!(matches!(syntax, RawQuerySyntax::CreateIndex(_, _)));
|
||||||
match operation {
|
match syntax {
|
||||||
Operation::CreateIndex(table_name, column_name) => {
|
RawQuerySyntax::CreateIndex(table_name, column_name) => {
|
||||||
assert_eq!(table_name, "contacts");
|
assert_eq!(table_name, "contacts");
|
||||||
assert_eq!(column_name, "email");
|
assert_eq!(column_name, "email");
|
||||||
}
|
}
|
||||||
|
|
@ -57,10 +57,10 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_create_index_with_spaces() {
|
fn test_create_index_with_spaces() {
|
||||||
let (_, operation) = parse_create_index("CREATE UNIQUE INDEX idxcontactsemail ON \"contacts\" ( email ) ;").expect("should parse");
|
let (_, syntax) = parse_create_index("CREATE UNIQUE INDEX idxcontactsemail ON \"contacts\" ( email ) ;").expect("should parse");
|
||||||
assert!(matches!(operation, Operation::CreateIndex(_, _)));
|
assert!(matches!(syntax, RawQuerySyntax::CreateIndex(_, _)));
|
||||||
match operation {
|
match syntax {
|
||||||
Operation::CreateIndex(table_name, column_name) => {
|
RawQuerySyntax::CreateIndex(table_name, column_name) => {
|
||||||
assert_eq!(table_name, "contacts");
|
assert_eq!(table_name, "contacts");
|
||||||
assert_eq!(column_name, "email");
|
assert_eq!(column_name, "email");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use super::{literal::parse_db_value, common::{parse_table_name, parse_identifier}};
|
use super::{literal::parse_db_value, common::{parse_table_name, parse_identifier}};
|
||||||
use minisql::{operation::Operation, type_system::Value};
|
use crate::syntax::RawQuerySyntax;
|
||||||
|
use minisql::type_system::Value;
|
||||||
use nom::{
|
use nom::{
|
||||||
bytes::complete::tag,
|
bytes::complete::tag,
|
||||||
character::complete::{multispace0, multispace1, char},
|
character::complete::{multispace0, multispace1, char},
|
||||||
|
|
@ -9,7 +10,7 @@ use nom::{
|
||||||
IResult,
|
IResult,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn parse_insert(input: &str) -> IResult<&str, Operation> {
|
pub fn parse_insert(input: &str) -> IResult<&str, RawQuerySyntax> {
|
||||||
let (input, _) = tag("INSERT")(input)?;
|
let (input, _) = tag("INSERT")(input)?;
|
||||||
let (input, _) = multispace1(input)?;
|
let (input, _) = multispace1(input)?;
|
||||||
let (input, _) = tag("INTO")(input)?;
|
let (input, _) = tag("INTO")(input)?;
|
||||||
|
|
@ -33,7 +34,7 @@ pub fn parse_insert(input: &str) -> IResult<&str, Operation> {
|
||||||
let (input, _) = char(';')(input)?;
|
let (input, _) = char(';')(input)?;
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
Operation::Insert(table_name.to_string(), column_names.into_iter().zip(values).collect()),
|
RawQuerySyntax::Insert(table_name.to_string(), column_names.into_iter().zip(values).collect()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,17 +49,18 @@ pub fn parse_values(input: &str) -> IResult<&str, Vec<Value>> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use minisql::{operation::Operation, type_system::{IndexableValue, Value}};
|
use minisql::type_system::{IndexableValue, Value};
|
||||||
|
|
||||||
|
use crate::syntax::RawQuerySyntax;
|
||||||
use super::parse_insert;
|
use super::parse_insert;
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_insert() {
|
fn test_parse_insert() {
|
||||||
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");
|
let syntax = parse_insert(sql).expect("should parse");
|
||||||
match operation {
|
match syntax {
|
||||||
("", Operation::Insert(table_name, insertion_values)) => {
|
("", RawQuerySyntax::Insert(table_name, insertion_values)) => {
|
||||||
assert_eq!(table_name, "MyTable");
|
assert_eq!(table_name, "MyTable");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
insertion_values,
|
insertion_values,
|
||||||
|
|
@ -78,7 +80,7 @@ mod tests {
|
||||||
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");
|
let operation = parse_insert(sql).expect("should parse");
|
||||||
match operation {
|
match operation {
|
||||||
("", Operation::Insert(table_name, insertion_values)) => {
|
("", RawQuerySyntax::Insert(table_name, insertion_values)) => {
|
||||||
assert_eq!(table_name, "MyTable");
|
assert_eq!(table_name, "MyTable");
|
||||||
assert_eq!(insertion_values,
|
assert_eq!(insertion_values,
|
||||||
vec![
|
vec![
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::common::{parse_table_name, parse_column_name, parse_condition};
|
use super::common::{parse_table_name, parse_column_name, parse_condition};
|
||||||
use minisql::operation::{ColumnSelection, Operation};
|
use crate::syntax::{ColumnSelection, RawQuerySyntax};
|
||||||
use nom::{
|
use nom::{
|
||||||
branch::alt,
|
branch::alt,
|
||||||
bytes::complete::tag,
|
bytes::complete::tag,
|
||||||
|
|
@ -11,7 +11,7 @@ use nom::{
|
||||||
IResult,
|
IResult,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn parse_select(input: &str) -> IResult<&str, Operation> {
|
pub fn parse_select(input: &str) -> IResult<&str, RawQuerySyntax> {
|
||||||
let (input, _) = tag("SELECT")(input)?;
|
let (input, _) = tag("SELECT")(input)?;
|
||||||
let (input, _) = multispace1(input)?;
|
let (input, _) = multispace1(input)?;
|
||||||
|
|
||||||
|
|
@ -27,7 +27,7 @@ pub fn parse_select(input: &str) -> IResult<&str, Operation> {
|
||||||
let (input, _) = tag(";")(input)?;
|
let (input, _) = tag(";")(input)?;
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
Operation::Select(table_name.to_string(), column_selection, condition),
|
RawQuerySyntax::Select(table_name.to_string(), column_selection, condition),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,7 +44,7 @@ pub fn try_parse_column_selection(input: &str) -> IResult<&str, ColumnSelection>
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use minisql::operation::{ColumnSelection, Operation};
|
use crate::syntax::{ColumnSelection, RawQuerySyntax};
|
||||||
use crate::parsing::{common::{parse_column_name, parse_table_name}, select::parse_select};
|
use crate::parsing::{common::{parse_column_name, parse_table_name}, select::parse_select};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -53,7 +53,7 @@ mod tests {
|
||||||
let sql = "SELECT * FROM \"MyTable\";";
|
let sql = "SELECT * FROM \"MyTable\";";
|
||||||
let operation = parse_select(sql).expect("should parse");
|
let operation = parse_select(sql).expect("should parse");
|
||||||
match operation {
|
match operation {
|
||||||
("", Operation::Select(table_name, column_selection, maybe_condition)) => {
|
("", RawQuerySyntax::Select(table_name, column_selection, maybe_condition)) => {
|
||||||
assert_eq!(table_name, "MyTable");
|
assert_eq!(table_name, "MyTable");
|
||||||
assert!(matches!(column_selection, ColumnSelection::All));
|
assert!(matches!(column_selection, ColumnSelection::All));
|
||||||
assert!(matches!(maybe_condition, None));
|
assert!(matches!(maybe_condition, None));
|
||||||
|
|
@ -80,7 +80,7 @@ mod tests {
|
||||||
let sql = "SELECT name , email FROM \"AddressBook\" ;";
|
let sql = "SELECT name , email FROM \"AddressBook\" ;";
|
||||||
let operation = parse_select(sql).expect("should parse");
|
let operation = parse_select(sql).expect("should parse");
|
||||||
match operation {
|
match operation {
|
||||||
("", Operation::Select(table_name, column_selection, maybe_condition)) => {
|
("", RawQuerySyntax::Select(table_name, column_selection, maybe_condition)) => {
|
||||||
assert_eq!(table_name, "AddressBook");
|
assert_eq!(table_name, "AddressBook");
|
||||||
assert!(matches!(column_selection, ColumnSelection::Columns(_)));
|
assert!(matches!(column_selection, ColumnSelection::Columns(_)));
|
||||||
match column_selection {
|
match column_selection {
|
||||||
|
|
@ -102,11 +102,11 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_select_where() {
|
fn test_parse_select_where() {
|
||||||
use minisql::operation::Condition;
|
use crate::syntax::Condition;
|
||||||
let sql = "SELECT * FROM \"AddressBook\" WHERE id = 5 ;";
|
let sql = "SELECT * FROM \"AddressBook\" WHERE id = 5 ;";
|
||||||
let operation = parse_select(sql).expect("should parse");
|
let operation = parse_select(sql).expect("should parse");
|
||||||
match operation {
|
match operation {
|
||||||
("", Operation::Select(table_name, column_selection, maybe_condition)) => {
|
("", RawQuerySyntax::Select(table_name, column_selection, maybe_condition)) => {
|
||||||
assert_eq!(table_name, "AddressBook");
|
assert_eq!(table_name, "AddressBook");
|
||||||
assert!(matches!(column_selection, ColumnSelection::All));
|
assert!(matches!(column_selection, ColumnSelection::All));
|
||||||
assert!(matches!(maybe_condition, Some(Condition::Eq(_, _))));
|
assert!(matches!(maybe_condition, Some(Condition::Eq(_, _))));
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::syntax::{ColumnSelection, Condition, InsertionValues, RawQuerySyntax};
|
use crate::syntax::{ColumnSelection, Condition, InsertionValues, RawQuerySyntax};
|
||||||
use minisql::{operation::{ColumnSelectionForInterpreter, ConditionForInterpreter, InsertionValuesForInterpreter, OperationForInterpreter}, type_system::Value, schema::{TableSchema, ColumnName, TableName}, type_system::DbType, interpreter::TablePosition};
|
use minisql::{operation::{ColumnSelectionForInterpreter, ConditionForInterpreter, InsertionValuesForInterpreter, OperationForInterpreter}, type_system::Value, schema::{TableSchema, ColumnName, TableName}, type_system::DbType, interpreter::{TablePosition, DbSchema}};
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum ValidationError {
|
pub enum ValidationError {
|
||||||
|
|
@ -25,8 +25,6 @@ pub enum ValidationError {
|
||||||
RequiredColumnsAreMissing(Vec<ColumnName>)
|
RequiredColumnsAreMissing(Vec<ColumnName>)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type DbSchema<'a> = Vec<(TableName, TablePosition, &'a TableSchema)>;
|
|
||||||
|
|
||||||
/// Validates and converts the raw syntax into a proper interpreter operation based on db schema.
|
/// Validates and converts the raw syntax into a proper interpreter operation based on db schema.
|
||||||
pub fn validate_operation(query: RawQuerySyntax, db_schema: &DbSchema) -> Result<OperationForInterpreter, ValidationError> {
|
pub fn validate_operation(query: RawQuerySyntax, db_schema: &DbSchema) -> Result<OperationForInterpreter, ValidationError> {
|
||||||
match query {
|
match query {
|
||||||
|
|
|
||||||
|
|
@ -53,10 +53,10 @@ async fn handle_stream(mut stream: TcpStream) -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
FrontendMessage::Query(data) => {
|
FrontendMessage::Query(data) => {
|
||||||
println!("Received Query: {:?}", data);
|
println!("Received Query: {:?}", data);
|
||||||
let metadata = state.metadata();
|
let db_schema = state.db_schema();
|
||||||
match parse_and_validate(data.query.as_str().to_string(), &metadata) {
|
match parse_and_validate(data.query.as_str().to_string(), &db_schema) {
|
||||||
Ok(operation) => {
|
Ok(operation) => {
|
||||||
match state.interpret(operation) {
|
match state.interpret_for_interpreter(operation) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
send_query_response(&mut writer).await?;
|
send_query_response(&mut writer).await?;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue