From f7a6cc2549fa7d1a86eff04868aec28df638feeb Mon Sep 17 00:00:00 2001 From: Yuriy Dupyn <2153100+omedusyo@users.noreply.github.com> Date: Fri, 29 Dec 2023 07:24:46 +0100 Subject: [PATCH] Make Row a wrapper type --- minisql/src/base.rs | 9 ++- minisql/src/interpreter.rs | 2 +- minisql/src/table.rs | 111 ++++++++++++++++++++++++++++--------- minisql/src/type_system.rs | 2 +- 4 files changed, 91 insertions(+), 33 deletions(-) diff --git a/minisql/src/base.rs b/minisql/src/base.rs index eeb74a1..7163840 100644 --- a/minisql/src/base.rs +++ b/minisql/src/base.rs @@ -93,7 +93,7 @@ impl TableSchema { return Err(Error::MismatchBetweenInsertValuesAndColumns(self.table_name.clone(), insertion_values)) } - let mut row: Row = Vec::with_capacity(number_of_columns); + let mut row: Row = Row::with_number_of_columns(number_of_columns); let mut values: HashMap = HashMap::new(); for (column_name, db_value) in &insertion_values { @@ -112,11 +112,11 @@ impl TableSchema { } } - let id = match row.get(self.primary_key) { + let id: UUID = match row.get(self.primary_key) { Some(val) => { match val { DbValue::Indexable(IndexableDbValue::UUID(id)) => { - id + *id }, _ => unreachable!() @@ -126,7 +126,6 @@ impl TableSchema { unreachable!() }; - Ok((*id, row)) + Ok((id, row)) } - } diff --git a/minisql/src/interpreter.rs b/minisql/src/interpreter.rs index 050d3a8..3037d82 100644 --- a/minisql/src/interpreter.rs +++ b/minisql/src/interpreter.rs @@ -68,7 +68,7 @@ impl State { // the client, but the details of communication are hidden behind an interface // // writer: impl SqlResponseConsumer - pub fn interpret(&mut self, operation: Operation) -> DbResult { + pub fn interpret(&mut self, operation: Operation) -> DbResult { // TODO: lock stuff use Operation::*; diff --git a/minisql/src/table.rs b/minisql/src/table.rs index 716a940..01e11ec 100644 --- a/minisql/src/table.rs +++ b/minisql/src/table.rs @@ -1,43 +1,102 @@ use std::collections::{BTreeMap, HashMap, HashSet}; +use std::slice::SliceIndex; +use std::ops::{Index, IndexMut}; use crate::base::{TableSchema, ColumnPosition, ColumnName, DbResult}; use crate::type_system::{UUID, DbValue, IndexableDbValue}; use crate::column_index::ColumnIndex; use crate::error::Error; -#[derive(Debug)] -pub struct Table { - pub schema: TableSchema, - pub rows: Rows, // TODO: Consider wrapping this in a lock. Also consider if we need to have the - // same lock for both rows and indexes - pub indexes: - HashMap // TODO: Consider generalizing `ColumnPosition` to something that would also apply to a pair of `ColumnNames` etc -} - - +// ======Table Row====== pub type Rows = // 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 BTreeMap; // Use `ColumnPosition` as index -pub type Row = Vec; +#[derive(Debug, Clone)] +pub struct Row(Vec); -fn restrict_columns(row: &Row, columns: &Vec) -> Row { - // If the index from `columns` is non-existant in `row`, it will just ignore it. - let mut subrow: Row = vec![]; - for column_position in columns { - match row.get(*column_position) { - Some(value) => { - subrow.push(value.clone()) - }, - None => {} - } +impl Index for Row +where + Idx: SliceIndex<[DbValue]>, +{ + type Output = Idx::Output; + + fn index(&self, index: Idx) -> &Self::Output { + &self.0[index] } - subrow } +impl IndexMut for Row +where + Idx: SliceIndex<[DbValue]>, +{ + fn index_mut(&mut self, index: Idx) -> &mut Self::Output { + &mut self.0[index] + } +} + +impl FromIterator for Row { + fn from_iter>(iter: I) -> Self { + let mut v = vec![]; + for x in iter { + v.push(x) + } + Row(v) + } +} + +impl Row { + pub fn new() -> Self { + Row(vec![]) + } + + pub fn with_number_of_columns(number_of_columns: usize) -> Self { + Row(Vec::with_capacity(number_of_columns)) + } + + pub fn push(&mut self, value: DbValue) { + self.0.push(value) + } + + pub fn len(&self) -> usize { + self.0.len() + } + + pub fn get(&self, column_position: ColumnPosition) -> Option<&DbValue> { + self.0.get(column_position) + } + + pub fn restrict_columns(&self, columns: &Vec) -> Row { + // If the index from `columns` is non-existant in `row`, it will just ignore it. + let mut subrow: Row = Row::new(); + for column_position in columns { + match self.get(*column_position) { + Some(value) => { + subrow.0.push(value.clone()) + }, + None => {} + } + } + subrow + } + +} + + +// ======Table====== +#[derive(Debug)] +pub struct Table { + pub schema: TableSchema, + pub rows: Rows, // TODO: Consider wrapping this in a lock. Also consider if we need to have the + // same lock for both rows and indexes + pub indexes: + HashMap +} + + impl Table { pub fn new(table_schema: TableSchema) -> Self { Self { @@ -66,7 +125,7 @@ impl Table { } pub fn select_all_rows(&self, selected_column_positions: &Vec) -> Vec { - self.rows.values().map(|row| restrict_columns(row, &selected_column_positions)).collect() + self.rows.values().map(|row| row.restrict_columns(&selected_column_positions)).collect() } pub fn select_rows_where_eq(&self, selected_column_positions: &Vec, column_position: ColumnPosition, value: DbValue) -> DbResult> { @@ -74,13 +133,13 @@ impl Table { 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()), + Ok(self.get_rows_by_ids(ids).iter().map(|row| row.restrict_columns(&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, &DbValue::Indexable(value)).iter().map(|row| row.restrict_columns(&selected_column_positions)).collect()) } }, _ => { - Ok(self.get_rows_by_value(column_position, &value).iter().map(|row| restrict_columns(row, &selected_column_positions)).collect()) + Ok(self.get_rows_by_value(column_position, &value).iter().map(|row| row.restrict_columns(&selected_column_positions)).collect()) } } } diff --git a/minisql/src/type_system.rs b/minisql/src/type_system.rs index 15c46b9..a6b1ce5 100644 --- a/minisql/src/type_system.rs +++ b/minisql/src/type_system.rs @@ -29,7 +29,7 @@ pub enum IndexableDbValue { } impl DbValue { - fn to_type(self) -> DbType { + pub fn to_type(self) -> DbType { match self { Self::Number(_) => DbType::Number, Self::Indexable(val) =>