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 // table-metadata and data
type TableName = String; type TableName = String;
type TablePosition = u32; type TablePosition = usize;
struct Table { struct Table {
schema: TableSchema, schema: TableSchema,
@ -117,10 +117,6 @@ struct TableSchema {
types: Vec<DbType>, types: Vec<DbType>,
} }
// TODO
fn column_position(table_meta: TableSchema, column_name: ColumnName) -> Option<ColumnPosition> {
todo!()
}
// Use `TablePosition` as index // Use `TablePosition` as index
type Tables = Vec<Table>; type Tables = Vec<Table>;
@ -146,17 +142,35 @@ fn select_columns(row: &Row, columns: &Vec<ColumnPosition>) -> Row {
// ==============Interpreter================ // ==============Interpreter================
struct State { struct State {
table_positions: HashMap<TableName, TablePosition>, table_name_position_mapping: BiMap<TableName, TablePosition>,
tables: Vec<Table>, tables: Vec<Table>,
} }
impl State { impl State {
fn table_from_name<'b: 'a, 'a>(&'b self, table_name: TableName) -> Option<&'a Table> { fn table_from_name<'b: 'a, 'a>(&'b self, table_name: &TableName) -> DbResult<&'a Table> {
todo!() 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) { 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:
} }
// 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, // 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. // 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 // 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 { match operation {
Select(table_name, column_selection, maybe_condition) => { 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)?)) Ok(Response::Selected(table.select_where(column_selection, maybe_condition)?))
}, },
Insert(table_name, values) => { Insert(table_name, values) => {
let table: &mut Table = todo!(); let table: &mut Table = state.table_from_name_mut(&table_name)?;
let _ = table.insert(values)?; let _ = table.insert(values)?;
Ok(Response::Inserted()) Ok(Response::Inserted)
}, },
Delete(table_name, maybe_condition) => { 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)?; let rows_affected = table.delete_where(maybe_condition)?;
Ok(Response::Deleted(rows_affected)) 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) => { CreateTable(table_name, table_schema) => {
let table = Table::new(table_schema); let table = Table::new(table_schema);
state.attach_table(table_name, table); state.attach_table(table_name, table);
todo!() Ok(Response::TableCreated)
}, },
CreateIndex(table_name, column_name) => { CreateIndex(table_name, column_name) => {
let table: &mut Table = todo!(); // TODO: This is incomplete. It can happen that an index is created
let column_position: ColumnPosition = todo!(); // 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); table.attach_index(column_position, index);
todo!() Ok(Response::IndexCreated)
}, },
} }
} }
impl ColumnIndex { impl ColumnIndex {
fn new() -> Self { fn new(rows: &Rows) -> Self {
Self { index: BTreeMap::new() } 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 { fn is_primary(&self, column_position: ColumnPosition) -> bool {
self.primary_key == column_position self.primary_key == column_position
} }
@ -243,7 +260,7 @@ impl TableSchema {
fn column_positions_from_column_names(&self, column_names: &[ColumnName]) -> DbResult<Vec<ColumnPosition>> { fn column_positions_from_column_names(&self, column_names: &[ColumnName]) -> DbResult<Vec<ColumnPosition>> {
let mut positions: Vec<ColumnPosition> = Vec::with_capacity(column_names.len()); let mut positions: Vec<ColumnPosition> = Vec::with_capacity(column_names.len());
for column_name in column_names { 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) positions.push(column_position)
} }
Ok(positions) Ok(positions)
@ -512,14 +529,17 @@ impl ColumnIndex {
enum Response { enum Response {
Selected(Vec<Row>), Selected(Vec<Row>),
Inserted(), Inserted,
Deleted(usize), // how many were deleted Deleted(usize), // how many were deleted
TableCreated,
IndexCreated,
} }
type DbResult<A> = Result<A, Error>; type DbResult<A> = Result<A, Error>;
// #[derive(Debug)] // #[derive(Debug)]
enum Error { enum Error {
TableDoesNotExist(TableName),
ColumnDoesNotExist(TableName, ColumnName), ColumnDoesNotExist(TableName, ColumnName),
ColumnPositionDoesNotExist(TableName, ColumnPosition), ColumnPositionDoesNotExist(TableName, ColumnPosition),
ValueDoesNotMatchExpectedType(TableName, ColumnName, DbType, DbValue), ValueDoesNotMatchExpectedType(TableName, ColumnName, DbType, DbValue),