Refine CREATE TABLE and CREATE INDEX

This commit is contained in:
Yuriy Dupyn 2023-12-11 21:59:01 +01:00
parent d555e8565f
commit 0aa3b28e74

View file

@ -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<DbType>,
}
// TODO
fn column_position(table_meta: TableSchema, column_name: ColumnName) -> Option<ColumnPosition> {
todo!()
}
// Use `TablePosition` as index
type Tables = Vec<Table>;
@ -146,17 +142,35 @@ fn select_columns(row: &Row, columns: &Vec<ColumnPosition>) -> Row {
// ==============Interpreter================
struct State {
table_positions: HashMap<TableName, TablePosition>,
table_name_position_mapping: BiMap<TableName, TablePosition>,
tables: Vec<Table>,
}
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<ColumnPosition> {
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<Vec<ColumnPosition>> {
let mut positions: Vec<ColumnPosition> = 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<Row>),
Inserted(),
Inserted,
Deleted(usize), // how many were deleted
TableCreated,
IndexCreated,
}
type DbResult<A> = Result<A, Error>;
// #[derive(Debug)]
enum Error {
TableDoesNotExist(TableName),
ColumnDoesNotExist(TableName, ColumnName),
ColumnPositionDoesNotExist(TableName, ColumnPosition),
ValueDoesNotMatchExpectedType(TableName, ColumnName, DbType, DbValue),