From 0aa3b28e7489e0e19d4c4900a9bb9ecce6b6dbdb Mon Sep 17 00:00:00 2001 From: Yuriy Dupyn <2153100+omedusyo@users.noreply.github.com> Date: Mon, 11 Dec 2023 21:59:01 +0100 Subject: [PATCH] Refine CREATE TABLE and CREATE INDEX --- src/main.rs | 78 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 29 deletions(-) diff --git a/src/main.rs b/src/main.rs index 142732a..8c4ec20 100644 --- a/src/main.rs +++ b/src/main.rs @@ -90,7 +90,7 @@ impl DbValue { // table-metadata and data type TableName = String; -type TablePosition = u32; +type TablePosition = usize; struct Table { schema: TableSchema, @@ -117,10 +117,6 @@ struct TableSchema { types: Vec, } -// TODO -fn column_position(table_meta: TableSchema, column_name: ColumnName) -> Option { - todo!() -} // Use `TablePosition` as index type Tables = Vec; @@ -146,17 +142,35 @@ fn select_columns(row: &Row, columns: &Vec) -> Row { // ==============Interpreter================ struct State { - table_positions: HashMap, + table_name_position_mapping: BiMap, tables: Vec
, } impl State { - fn table_from_name<'b: 'a, 'a>(&'b self, table_name: TableName) -> Option<&'a Table> { - todo!() + fn table_from_name<'b: 'a, 'a>(&'b self, table_name: &TableName) -> DbResult<&'a Table> { + match self.table_name_position_mapping.get_by_left(table_name) { + Some(table_position) => { + let table = &self.tables[*table_position]; + Ok(table) + }, + None => Err(Error::TableDoesNotExist(table_name.clone())) + } + } + + fn table_from_name_mut<'b: 'a, 'a>(&'b mut self, table_name: &TableName) -> DbResult<&'a mut Table> { + match self.table_name_position_mapping.get_by_left(table_name) { + Some(table_position) => { + let table = &mut self.tables[*table_position]; + Ok(table) + }, + None => Err(Error::TableDoesNotExist(table_name.clone())) + } } fn attach_table(&mut self, table_name: TableName, table: Table) { - todo!() + let new_table_position: TablePosition = self.tables.len(); + self.table_name_position_mapping.insert(table_name, new_table_position); + self.tables.push(table); } } @@ -165,13 +179,6 @@ trait SqlConsumer { // TODO: } -// TODO: This should return a reference to the table -// 'tables_life contains 'table_life -fn get_table<'tables_life: 'table_life, 'table_life>(tables: &'tables_life Tables, table_name: &TableName) -> &'table_life Table { - // let table_position: - todo!() -} - // TODO: Decide if we want for this to return a response (but then you have to deal with lifetimes, // because you'll be forced to put an iterator/slice into the Response data-structure. // Alternative is to pass a row-consumer to the functionas that knows how to communicate with @@ -182,17 +189,17 @@ fn interpret(table_name: TableName, operation: Operation, state: &mut State, con match operation { Select(table_name, column_selection, maybe_condition) => { - let table: &Table = todo!(); + let table: &Table = state.table_from_name(&table_name)?; Ok(Response::Selected(table.select_where(column_selection, maybe_condition)?)) }, Insert(table_name, values) => { - let table: &mut Table = todo!(); + let table: &mut Table = state.table_from_name_mut(&table_name)?; let _ = table.insert(values)?; - Ok(Response::Inserted()) + Ok(Response::Inserted) }, Delete(table_name, maybe_condition) => { - let table: &mut Table = todo!(); + let table: &mut Table = state.table_from_name_mut(&table_name)?; let rows_affected = table.delete_where(maybe_condition)?; Ok(Response::Deleted(rows_affected)) @@ -200,22 +207,28 @@ fn interpret(table_name: TableName, operation: Operation, state: &mut State, con CreateTable(table_name, table_schema) => { let table = Table::new(table_schema); state.attach_table(table_name, table); - todo!() + Ok(Response::TableCreated) }, CreateIndex(table_name, column_name) => { - let table: &mut Table = todo!(); - let column_position: ColumnPosition = todo!(); + // TODO: This is incomplete. It can happen that an index is created + // after the table has some rows for a while. + // In such a case the index needs to be built over all those existing rows. + let table: &mut Table = state.table_from_name_mut(&table_name)?; + let column_position: ColumnPosition = table.schema.column_position_from_column_name(&column_name)?; - let index: ColumnIndex = ColumnIndex::new(); + let index: ColumnIndex = ColumnIndex::new(&table.rows); table.attach_index(column_position, index); - todo!() + Ok(Response::IndexCreated) }, } } impl ColumnIndex { - fn new() -> Self { - Self { index: BTreeMap::new() } + fn new(rows: &Rows) -> Self { + let index = BTreeMap::new(); + // TODO: Take into account already existing rows + todo!(); + Self { index } } } @@ -236,6 +249,10 @@ impl TableSchema { } } + fn column_position_from_column_name(&self, column_name: &ColumnName) -> DbResult { + self.get_column(column_name).map(|(_, column_position)| column_position) + } + fn is_primary(&self, column_position: ColumnPosition) -> bool { self.primary_key == column_position } @@ -243,7 +260,7 @@ impl TableSchema { fn column_positions_from_column_names(&self, column_names: &[ColumnName]) -> DbResult> { let mut positions: Vec = Vec::with_capacity(column_names.len()); for column_name in column_names { - let (_, column_position) = self.get_column(column_name)?; + let column_position = self.column_position_from_column_name(column_name)?; positions.push(column_position) } Ok(positions) @@ -512,14 +529,17 @@ impl ColumnIndex { enum Response { Selected(Vec), - Inserted(), + Inserted, Deleted(usize), // how many were deleted + TableCreated, + IndexCreated, } type DbResult = Result; // #[derive(Debug)] enum Error { + TableDoesNotExist(TableName), ColumnDoesNotExist(TableName, ColumnName), ColumnPositionDoesNotExist(TableName, ColumnPosition), ValueDoesNotMatchExpectedType(TableName, ColumnName, DbType, DbValue),