From 7bdb396d9ea78f4c271970150b4a77237174aa1a Mon Sep 17 00:00:00 2001 From: apakhomov Date: Tue, 22 Oct 2024 22:07:20 +0300 Subject: [PATCH] CREATE table support --- src/parser/mod.rs | 337 +++++++++++++++++----------------------------- 1 file changed, 123 insertions(+), 214 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 08cfe21..dc1ae63 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -4,197 +4,6 @@ pub mod lexer; use lexer::tokens::Token; -/// -/// TREE STRUCTURE -/// -/// *Queries*: -/// select col1, col2 from table1; -/// insert into table1 (col1, col2) values (1, 'valStr'); -/// insert into table1 (col1) values (1); -#[derive(Debug, PartialEq)] -struct Queries { - queries: Vec, -} - -#[derive(Debug, PartialEq)] -enum Query { - // select ... - Select(SelectQuery), - // insert ... - Insert(InsertQuery), - // delete ... - Delete(DeleteQuery), - // update ... - Update(UpdateQuery), - // create table ... - CreateTable(CreateTableQuery), - // drop table ... - DropTable(DropTableQuery), - // alter table ... AlterTable(AlterTableQuery), -} - -/// *SelectQuery*: -/// select -/// from -/// where -/// order by -/// group by -/// having -/// limit -#[derive(Debug, PartialEq)] -struct SelectQuery { - select_statement: SelectStatement, - from_statement: FromStatement, - where_statement: Option, - order_by_statement: Option, - group_by_statement: Option, - having_statement: Option, - limit_statement: Option, -} - -/// *InsertQuery*: -/// insert into () values () -#[derive(Debug, PartialEq)] -struct InsertQuery { - table_name: String, - columns: Vec, - values: Vec, -} - -/// *DeleteQuery*: -/// delete from where -#[derive(Debug, PartialEq)] -struct DeleteQuery { - table_name: String, - where_statement: Option, -} - -/// *UpdateQuery*: -/// update set where -#[derive(Debug, PartialEq)] -struct UpdateQuery { - table_name: String, - set_statement: SetStatement, - where_statement: Option, -} - -/// *CreateTableQuery*: -/// create table () -#[derive(Debug, PartialEq)] -struct CreateTableQuery { - table_name: String, - // TODO: Design this - columns_definitions: Vec, - // TODO: Design this - constraints: Vec, -} - -/// *DropTableQuery*: -/// drop table -#[derive(Debug, PartialEq)] -struct DropTableQuery { - table_name: String, -} - -/// *AlterTableQuery*: -/// alter table -#[derive(Debug, PartialEq)] -struct AlterTableQuery { - table_name: String, - // TODO: Design this - action: String, -} - -#[derive(Debug, PartialEq)] -struct SelectStatement { - columns: Vec, - distinct: bool, -} - -#[derive(Debug, PartialEq)] -struct FromStatement { - tables: Vec, - joins: Vec, -} - -#[derive(Debug, PartialEq)] -struct TableStatement { - table_name: String, - alias: Option, -} - -#[derive(Debug, PartialEq)] -struct JoinStatement { - table: TableStatement, - // TODO: Design this - join_type: String, - on: Vec, -} - -#[derive(Debug, PartialEq)] -struct Condition { - left: ColumnStatement, - operator: Operator, - right: ColumnStatement, -} - -#[derive(Debug, PartialEq)] -enum Operator { - Equal, - NotEqual, -} - -#[derive(Debug, PartialEq)] -struct WhereStatement { - conditions: Vec, -} - -#[derive(Debug, PartialEq)] -struct OrderByStatement { - columns: Vec, - order: Order, -} - -#[derive(Debug, PartialEq)] -enum Order { - Asc, - Desc, -} - -#[derive(Debug, PartialEq)] -struct LimitStatement { - limit: i32, -} - -#[derive(Debug, PartialEq)] -struct GroupByStatement { - columns: Vec, -} - -#[derive(Debug, PartialEq)] -struct HavingStatement { - conditions: Vec, -} - -#[derive(Debug, PartialEq)] -struct SetStatement { - // TODO: Design this - columns: Vec, -} - -#[derive(Debug, PartialEq)] -enum ColumnStatement { - Identifier(ColumnIdentifier), - Literal(Literal), - Function(Function), -} - -#[derive(Debug, PartialEq)] -struct ColumnIdentifier { - table_name: Option, - column_name: String, -} - #[derive(Debug, PartialEq)] pub enum Literal { Numeric(i32), @@ -205,7 +14,14 @@ pub enum Literal { third_name: Option, }, Float(f32), - Boolean(bool), + Bool(bool), +} + +#[derive(Debug, PartialEq)] +pub enum Type { + Int, + String, + Bool, } impl Literal { @@ -237,30 +53,10 @@ impl Literal { } } -#[derive(Debug, PartialEq)] -pub struct ColumnList { - columns: Vec, -} - -#[derive(Debug, PartialEq)] -pub struct TableList { - tables: Vec, -} - -#[derive(Debug, PartialEq)] -pub struct Where { - conditions: Vec, -} - -#[derive(Debug, PartialEq)] -struct Function { - name: String, - arguments: Vec, -} - #[derive(Debug, PartialEq)] pub enum Node { Leaf(Literal), + LeafType(Type), Infix(Op, Vec), Prefix(Op, Vec), @@ -294,6 +90,10 @@ pub enum Op { Select, From, Where, + + CreateTable, + + ColumnDefinition, } impl<'a> Parser<'a> { @@ -331,6 +131,7 @@ impl<'a> Parser<'a> { } } Some(Ok(Token::Select)) => self.parse_select(min_bp), + Some(Ok(Token::Create)) => self.parse_create(min_bp), s => panic!("Unexpected token: {:?}", s), }; @@ -378,6 +179,71 @@ impl<'a> Parser<'a> { lhs } + fn parse_create(&mut self, min_bp: u8) -> Node { + match self.lexer.next() { + Some(Ok(Token::Table)) => self.parse_create_table(min_bp), + s => panic!("Unexpected token: {:?}", s), + } + } + + fn parse_create_table(&mut self, _min_bp: u8) -> Node { + let lhs = match self.lexer.next() { + Some(Ok(Token::Identifier { + first_name, + second_name: None, + third_name: None, + })) => Literal::identifier(first_name), + s => panic!("Unexpected token: {:?}", s), + }; + + match self.lexer.next() { + Some(Ok(Token::OpenParen)) => { + let mut columns = vec![]; + + loop { + let column_name = match self.lexer.next() { + Some(Ok(Token::Identifier { + first_name, + second_name: None, + third_name: None, + })) => Literal::identifier(first_name), + Some(Ok(Token::CloseParen)) => break, + s => panic!("Unexpected token: {:?}", s), + }; + + match self.lexer.next() { + Some(Ok(Token::Int)) => { + columns.push(Node::Infix( + Op::ColumnDefinition, + vec![Node::Leaf(column_name), Node::LeafType(Type::Int)], + )); + } + s => panic!("Unexpected token: {:?}", s), + } + + match self.lexer.next() { + Some(Ok(Token::Comma)) => continue, + Some(Ok(Token::CloseParen)) => break, + s => panic!("Unexpected token: {:?}", s), + } + } + + if columns.len() == 1 { + Node::Prefix( + Op::CreateTable, + vec![Node::Leaf(lhs), columns.pop().unwrap()], + ) + } else { + Node::Prefix( + Op::CreateTable, + vec![Node::Leaf(lhs), Node::Infix(Op::Comma, columns)], + ) + } + } + s => panic!("Unexpected token: {:?}", s), + } + } + fn parse_select(&mut self, min_bp: u8) -> Node { let rhs = self.parse_bp(0); @@ -450,7 +316,7 @@ impl<'a> Parser<'a> { mod tests { use crate::parser::{Literal, Node, Op, Parser}; - use super::lexer::Lexer; + use super::{lexer::Lexer, Type}; use pretty_assertions::assert_eq; fn id(identifier: &str) -> Literal { @@ -465,6 +331,10 @@ mod tests { Node::Leaf(literal) } + fn leaf_type(typ: Type) -> Node { + Node::LeafType(typ) + } + fn infix(op: Op, lhs: Node, rhs: Node) -> Node { Node::Infix(op, vec![lhs, rhs]) } @@ -732,4 +602,43 @@ mod tests { ) ); } + + #[test] + fn create_table() { + let input = r" + create table table1 ( + col1 int, + col2 int + )"; + + assert_eq!( + parse(input), + prefix_chain( + Op::CreateTable, + leaf(id("table1")), + infix( + Op::Comma, + infix(Op::ColumnDefinition, leaf(id("col1")), leaf_type(Type::Int)), + infix(Op::ColumnDefinition, leaf(id("col2")), leaf_type(Type::Int)) + ) + ) + ); + } + + #[test] + fn create_table_with_single_column() { + let input = r" + create table table1 ( + col1 int + )"; + + assert_eq!( + dbg!(parse(input)), + prefix_chain( + Op::CreateTable, + leaf(id("table1")), + infix(Op::ColumnDefinition, leaf(id("col1")), leaf_type(Type::Int)) + ) + ); + } }