Simplify select_all and delete_all
This commit is contained in:
parent
6b58c3cb9b
commit
f9b874f302
2 changed files with 86 additions and 76 deletions
|
|
@ -86,7 +86,7 @@ impl State {
|
||||||
Delete(table_name, maybe_condition) => {
|
Delete(table_name, maybe_condition) => {
|
||||||
let table: &mut Table = self.table_from_name_mut(&table_name)?;
|
let table: &mut Table = self.table_from_name_mut(&table_name)?;
|
||||||
|
|
||||||
let rows_affected = table.delete_where(maybe_condition)?;
|
let rows_affected = table.delete_rows_where(maybe_condition)?;
|
||||||
Ok(Response::Deleted(rows_affected))
|
Ok(Response::Deleted(rows_affected))
|
||||||
},
|
},
|
||||||
CreateTable(table_name, table_schema) => {
|
CreateTable(table_name, table_schema) => {
|
||||||
|
|
|
||||||
|
|
@ -17,16 +17,13 @@ pub struct Table {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Use `ColumnPosition` as index
|
|
||||||
pub type Row = Vec<DbValue>;
|
|
||||||
|
|
||||||
pub type Rows =
|
pub type Rows =
|
||||||
// TODO: This should be some sort of an interface to a dictionary
|
// TODO: This should be some sort of an interface to a dictionary
|
||||||
// s.t. in the background it may modify stuff in memory or talk to the disk
|
// s.t. in the background it may modify stuff in memory or talk to the disk
|
||||||
BTreeMap<UUID, Row>;
|
BTreeMap<UUID, Row>;
|
||||||
|
|
||||||
// interface
|
// Use `ColumnPosition` as index
|
||||||
// insert(id, value)
|
pub type Row = Vec<DbValue>;
|
||||||
|
|
||||||
fn restrict_columns(row: &Row, columns: &Vec<ColumnPosition>) -> Row {
|
fn restrict_columns(row: &Row, columns: &Vec<ColumnPosition>) -> Row {
|
||||||
// If the index from `columns` is non-existant in `row`, it will just ignore it.
|
// If the index from `columns` is non-existant in `row`, it will just ignore it.
|
||||||
|
|
@ -51,10 +48,7 @@ impl Table {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn attach_index(&mut self, column_position: ColumnPosition, column_index: ColumnIndex) {
|
// ======Selection======
|
||||||
self.indexes.insert(column_position, column_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_row_by_id(&self, id: UUID) -> Option<Row> {
|
fn get_row_by_id(&self, id: UUID) -> Option<Row> {
|
||||||
self.rows.get(&id).cloned()
|
self.rows.get(&id).cloned()
|
||||||
}
|
}
|
||||||
|
|
@ -72,6 +66,61 @@ impl Table {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn select_all_rows(&self, selected_column_positions: &Vec<ColumnPosition>) -> Vec<Row> {
|
||||||
|
self.rows.values().map(|row| restrict_columns(row, &selected_column_positions)).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn select_rows_where_eq(&self, selected_column_positions: &Vec<ColumnPosition>, column_position: ColumnPosition, value: DbValue) -> DbResult<Vec<Row>> {
|
||||||
|
match value {
|
||||||
|
DbValue::Indexable(value) => {
|
||||||
|
match self.fetch_ids_from_index(column_position, &value)? {
|
||||||
|
Some(ids) =>
|
||||||
|
Ok(self.get_rows_by_ids(ids).iter().map(|row| restrict_columns(row, &selected_column_positions)).collect()),
|
||||||
|
None =>
|
||||||
|
Ok(self.get_rows_by_value(column_position, &DbValue::Indexable(value)).iter().map(|row| restrict_columns(row, &selected_column_positions)).collect())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
Ok(self.get_rows_by_value(column_position, &value).iter().map(|row| restrict_columns(row, &selected_column_positions)).collect())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn select_where(&self, column_selection: ColumnSelection, condition: Option<Condition>) -> DbResult<Vec<Row>> {
|
||||||
|
let selected_column_positions: Vec<ColumnPosition> = self.schema.column_positions_from_column_selection(&column_selection)?;
|
||||||
|
match condition {
|
||||||
|
None => Ok(self.select_all_rows(&selected_column_positions)),
|
||||||
|
|
||||||
|
Some(Condition::Eq(eq_column_name, value)) => {
|
||||||
|
let eq_column_position = self.schema.column_position_from_column_name(&eq_column_name)?;
|
||||||
|
self.select_rows_where_eq(&selected_column_positions, eq_column_position, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ======Insertion======
|
||||||
|
pub fn insert(&mut self, values: InsertionValues) -> DbResult<()> {
|
||||||
|
let (id, row) = self.schema.row_from_insertion_values(values)?;
|
||||||
|
|
||||||
|
if self.rows.get(&id).is_some() {
|
||||||
|
return Err(Error::AttemptingToInsertAlreadyPresentId(self.schema.table_name.clone(), id))
|
||||||
|
}
|
||||||
|
|
||||||
|
for (column_position, column_index) in &mut self.indexes {
|
||||||
|
match row.get(*column_position) {
|
||||||
|
Some(DbValue::Indexable(val)) => {
|
||||||
|
column_index.add(val.clone(), id)
|
||||||
|
},
|
||||||
|
Some(_) => {},
|
||||||
|
None => return Err(Error::ColumnPositionDoesNotExist(self.schema.table_name.clone(), *column_position))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = self.rows.insert(id, row);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// ======Deletion======
|
||||||
fn delete_row_by_id(&mut self, id: UUID) -> usize {
|
fn delete_row_by_id(&mut self, id: UUID) -> usize {
|
||||||
match self.rows.remove(&id) {
|
match self.rows.remove(&id) {
|
||||||
Some(row) => {
|
Some(row) => {
|
||||||
|
|
@ -101,82 +150,43 @@ impl Table {
|
||||||
self.delete_rows_by_ids(matched_ids)
|
self.delete_rows_by_ids(matched_ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_where(&self, column_selection: ColumnSelection, condition: Option<Condition>) -> DbResult<Vec<Row>> {
|
fn delete_all_rows(&mut self) -> usize {
|
||||||
let selected_column_positions = self.schema.column_positions_from_column_selection(&column_selection)?;
|
let number_of_rows = self.rows.len();
|
||||||
match condition {
|
self.rows = BTreeMap::new();
|
||||||
None =>
|
self.indexes = HashMap::new();
|
||||||
// select all
|
number_of_rows
|
||||||
Ok(self.rows.values().map(|row| restrict_columns(row, &selected_column_positions)).collect()),
|
}
|
||||||
|
|
||||||
Some(Condition::Eq(eq_column_name, value)) => {
|
fn delete_rows_where_eq(&mut self, column_position: ColumnPosition, value: DbValue) -> DbResult<usize> {
|
||||||
let eq_column_position = self.schema.column_position_from_column_name(&eq_column_name)?;
|
match value {
|
||||||
match value {
|
DbValue::Indexable(value) => {
|
||||||
DbValue::Indexable(value) => {
|
match self.fetch_ids_from_index(column_position, &value)? {
|
||||||
match self.fetch_ids_from_index(eq_column_position, &value)? {
|
Some(ids) =>
|
||||||
Some(ids) =>
|
Ok(self.delete_rows_by_ids(ids)),
|
||||||
Ok(self.get_rows_by_ids(ids).iter().map(|row| restrict_columns(row, &selected_column_positions)).collect()),
|
None =>
|
||||||
None =>
|
Ok(self.delete_rows_by_value(column_position, &DbValue::Indexable(value)))
|
||||||
Ok(self.get_rows_by_value(eq_column_position, &DbValue::Indexable(value)).iter().map(|row| restrict_columns(row, &selected_column_positions)).collect())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
Ok(self.get_rows_by_value(eq_column_position, &value).iter().map(|row| restrict_columns(row, &selected_column_positions)).collect())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert(&mut self, values: InsertionValues) -> DbResult<()> {
|
|
||||||
let (id, row) = self.schema.row_from_insertion_values(values)?;
|
|
||||||
|
|
||||||
if self.rows.get(&id).is_some() {
|
|
||||||
return Err(Error::AttemptingToInsertAlreadyPresentId(self.schema.table_name.clone(), id))
|
|
||||||
}
|
|
||||||
|
|
||||||
for (column_position, column_index) in &mut self.indexes {
|
|
||||||
match row.get(*column_position) {
|
|
||||||
Some(DbValue::Indexable(val)) => {
|
|
||||||
column_index.add(val.clone(), id)
|
|
||||||
},
|
|
||||||
Some(_) => {},
|
|
||||||
None => return Err(Error::ColumnPositionDoesNotExist(self.schema.table_name.clone(), *column_position))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let _ = self.rows.insert(id, row);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Split into delete all and delete_where(condition)
|
|
||||||
pub fn delete_where(&mut self, maybe_condition: Option<Condition>) -> DbResult<usize> {
|
|
||||||
match maybe_condition {
|
|
||||||
None => {
|
|
||||||
// delete all
|
|
||||||
let number_of_rows = self.rows.len();
|
|
||||||
self.rows = BTreeMap::new();
|
|
||||||
self.indexes = HashMap::new();
|
|
||||||
Ok(number_of_rows)
|
|
||||||
},
|
},
|
||||||
|
_ =>
|
||||||
|
Ok(self.delete_rows_by_value(column_position, &value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete_rows_where(&mut self, maybe_condition: Option<Condition>) -> DbResult<usize> {
|
||||||
|
match maybe_condition {
|
||||||
|
None => Ok(self.delete_all_rows()),
|
||||||
Some(Condition::Eq(eq_column_name, value)) => {
|
Some(Condition::Eq(eq_column_name, value)) => {
|
||||||
let eq_column_position = self.schema.column_position_from_column_name(&eq_column_name)?;
|
let eq_column_position = self.schema.column_position_from_column_name(&eq_column_name)?;
|
||||||
match value {
|
self.delete_rows_where_eq(eq_column_position, value)
|
||||||
DbValue::Indexable(value) => {
|
|
||||||
match self.fetch_ids_from_index(eq_column_position, &value)? {
|
|
||||||
Some(ids) =>
|
|
||||||
Ok(self.delete_rows_by_ids(ids)),
|
|
||||||
None =>
|
|
||||||
Ok(self.delete_rows_by_value(eq_column_position, &DbValue::Indexable(value)))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ =>
|
|
||||||
Ok(self.delete_rows_by_value(eq_column_position, &value))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ======Indexing======
|
||||||
|
pub fn attach_index(&mut self, column_position: ColumnPosition, column_index: ColumnIndex) {
|
||||||
|
self.indexes.insert(column_position, column_index);
|
||||||
|
}
|
||||||
|
|
||||||
fn fetch_ids_from_index(&self, column_position: ColumnPosition, value: &IndexableDbValue) -> DbResult<Option<HashSet<UUID>>> {
|
fn fetch_ids_from_index(&self, column_position: ColumnPosition, value: &IndexableDbValue) -> DbResult<Option<HashSet<UUID>>> {
|
||||||
if self.schema.is_primary(column_position) {
|
if self.schema.is_primary(column_position) {
|
||||||
match value {
|
match value {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue