Make Row a wrapper type

This commit is contained in:
Yuriy Dupyn 2023-12-29 07:24:46 +01:00
parent bfb5042896
commit f7a6cc2549
4 changed files with 91 additions and 33 deletions

View file

@ -93,7 +93,7 @@ impl TableSchema {
return Err(Error::MismatchBetweenInsertValuesAndColumns(self.table_name.clone(), insertion_values)) 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<ColumnName, DbValue> = HashMap::new(); let mut values: HashMap<ColumnName, DbValue> = HashMap::new();
for (column_name, db_value) in &insertion_values { 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) => { Some(val) => {
match val { match val {
DbValue::Indexable(IndexableDbValue::UUID(id)) => { DbValue::Indexable(IndexableDbValue::UUID(id)) => {
id *id
}, },
_ => _ =>
unreachable!() unreachable!()
@ -126,7 +126,6 @@ impl TableSchema {
unreachable!() unreachable!()
}; };
Ok((*id, row)) Ok((id, row))
} }
} }

View file

@ -1,43 +1,102 @@
use std::collections::{BTreeMap, HashMap, HashSet}; use std::collections::{BTreeMap, HashMap, HashSet};
use std::slice::SliceIndex;
use std::ops::{Index, IndexMut};
use crate::base::{TableSchema, ColumnPosition, ColumnName, DbResult}; use crate::base::{TableSchema, ColumnPosition, ColumnName, DbResult};
use crate::type_system::{UUID, DbValue, IndexableDbValue}; use crate::type_system::{UUID, DbValue, IndexableDbValue};
use crate::column_index::ColumnIndex; use crate::column_index::ColumnIndex;
use crate::error::Error; use crate::error::Error;
#[derive(Debug)] // ======Table Row======
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<ColumnPosition, ColumnIndex> // TODO: Consider generalizing `ColumnPosition` to something that would also apply to a pair of `ColumnNames` etc
}
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>;
// Use `ColumnPosition` as index // Use `ColumnPosition` as index
pub type Row = Vec<DbValue>; #[derive(Debug, Clone)]
pub struct Row(Vec<DbValue>);
fn restrict_columns(row: &Row, columns: &Vec<ColumnPosition>) -> Row { impl<Idx> Index<Idx> for Row
where
Idx: SliceIndex<[DbValue]>,
{
type Output = Idx::Output;
fn index(&self, index: Idx) -> &Self::Output {
&self.0[index]
}
}
impl<Idx> IndexMut<Idx> for Row
where
Idx: SliceIndex<[DbValue]>,
{
fn index_mut(&mut self, index: Idx) -> &mut Self::Output {
&mut self.0[index]
}
}
impl FromIterator<DbValue> for Row {
fn from_iter<I: IntoIterator<Item=DbValue>>(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<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.
let mut subrow: Row = vec![]; let mut subrow: Row = Row::new();
for column_position in columns { for column_position in columns {
match row.get(*column_position) { match self.get(*column_position) {
Some(value) => { Some(value) => {
subrow.push(value.clone()) subrow.0.push(value.clone())
}, },
None => {} None => {}
} }
} }
subrow 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<ColumnPosition, ColumnIndex>
}
impl Table { impl Table {
pub fn new(table_schema: TableSchema) -> Self { pub fn new(table_schema: TableSchema) -> Self {
Self { Self {
@ -66,7 +125,7 @@ impl Table {
} }
pub fn select_all_rows(&self, selected_column_positions: &Vec<ColumnPosition>) -> Vec<Row> { pub fn select_all_rows(&self, selected_column_positions: &Vec<ColumnPosition>) -> Vec<Row> {
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<ColumnPosition>, column_position: ColumnPosition, value: DbValue) -> DbResult<Vec<Row>> { pub fn select_rows_where_eq(&self, selected_column_positions: &Vec<ColumnPosition>, column_position: ColumnPosition, value: DbValue) -> DbResult<Vec<Row>> {
@ -74,13 +133,13 @@ impl Table {
DbValue::Indexable(value) => { DbValue::Indexable(value) => {
match self.fetch_ids_from_index(column_position, &value)? { match self.fetch_ids_from_index(column_position, &value)? {
Some(ids) => 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 => 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())
} }
} }
} }

View file

@ -29,7 +29,7 @@ pub enum IndexableDbValue {
} }
impl DbValue { impl DbValue {
fn to_type(self) -> DbType { pub fn to_type(self) -> DbType {
match self { match self {
Self::Number(_) => DbType::Number, Self::Number(_) => DbType::Number,
Self::Indexable(val) => Self::Indexable(val) =>