feat: return schema and column positions with select

This commit is contained in:
Jindřich Moravec 2024-01-23 20:56:07 +01:00
parent ebabf50291
commit 1d746430d2
5 changed files with 84 additions and 43 deletions

View file

@ -1,6 +1,7 @@
use crate::type_system::Value;
use std::ops::{Index, IndexMut};
use std::slice::SliceIndex;
use crate::restricted_row::RestrictedRow;
pub type ColumnPosition = usize;
@ -58,14 +59,15 @@ impl Row {
self.0.get(column_position)
}
pub fn restrict_columns(&self, columns: &Vec<ColumnPosition>) -> Row {
pub fn restrict_columns(&self, columns: &Vec<ColumnPosition>) -> RestrictedRow {
// If the index from `columns` is non-existant in `row`, it will just ignore it.
let mut subrow: Row = Row::new();
let mut subrow: Vec<(ColumnPosition, Value)> = vec![];
for column_position in columns {
if let Some(value) = self.get(*column_position) {
subrow.0.push(value.clone())
subrow.push((*column_position, value.clone()));
}
}
subrow
subrow.into()
}
}

View file

@ -3,6 +3,7 @@ use std::collections::{BTreeMap, HashMap, HashSet};
use crate::error::Error;
use crate::internals::column_index::ColumnIndex;
use crate::internals::row::{ColumnPosition, Row};
use crate::restricted_row::RestrictedRow;
use crate::schema::{ColumnName, TableSchema, TableName};
use crate::result::DbResult;
use crate::type_system::{IndexableValue, Uuid, Value};
@ -67,7 +68,7 @@ impl Table {
.collect()
}
pub fn select_all_rows<'a>(&'a self, selected_column_positions: Vec<ColumnPosition>) -> impl Iterator<Item=Row> + 'a {
pub fn select_all_rows<'a>(&'a self, selected_column_positions: Vec<ColumnPosition>) -> impl Iterator<Item=RestrictedRow> + 'a {
self.rows
.values()
.map(move |row| row.restrict_columns(&selected_column_positions))
@ -78,7 +79,7 @@ impl Table {
selected_column_positions: Vec<ColumnPosition>,
column_position: ColumnPosition,
value: Value,
) -> DbResult<impl Iterator<Item=Row> + 'a> {
) -> DbResult<impl Iterator<Item=RestrictedRow> + 'a> {
let restrict_columns_of_row = move |row: Row| row.restrict_columns(&selected_column_positions);
match value {
Value::Indexable(value) => match self.fetch_ids_from_index(column_position, &value)? {

View file

@ -1,11 +1,12 @@
use crate::error::Error;
use crate::internals::row::{ColumnPosition, Row};
use crate::internals::row::ColumnPosition;
use crate::schema::{TableName, TableSchema};
use crate::internals::table::Table;
use crate::operation::{ColumnSelection, Condition, Operation};
use crate::result::DbResult;
use crate::type_system::{DbType, IndexableValue, Value};
use bimap::BiMap;
use crate::restricted_row::RestrictedRow;
// Use `TablePosition` as index
pub type Tables = Vec<Table>;
@ -20,7 +21,7 @@ pub struct State {
// #[derive(Debug)]
pub enum Response<'a> {
Selected(Box<dyn Iterator<Item=Row> + 'a>),
Selected(&'a TableSchema, Box<dyn Iterator<Item=RestrictedRow> + 'a>),
Inserted,
Deleted(usize), // how many were deleted
TableCreated,
@ -31,7 +32,7 @@ impl std::fmt::Debug for Response<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
use Response::*;
match self {
Selected(_rows) =>
Selected(_schema, _rows) =>
// TODO: How can we iterate through the rows without having to take ownership of
// them?
f.write_str("Some rows... trust me"),
@ -99,7 +100,7 @@ impl State {
let selected_rows = match maybe_condition {
None => {
let x = table.select_all_rows(selected_column_positions);
Box::new(x) as Box<dyn Iterator<Item=Row> + 'a>
Box::new(x) as Box<dyn Iterator<Item=RestrictedRow> + 'a>
},
Some(Condition::Eq(eq_column_name, value)) => {
@ -112,11 +113,11 @@ impl State {
eq_column_position,
value,
)?;
Box::new(x) as Box<dyn Iterator<Item=Row> + 'a>
Box::new(x) as Box<dyn Iterator<Item=RestrictedRow> + 'a>
}
};
Ok(Response::Selected(selected_rows))
Ok(Response::Selected(table.schema(), selected_rows))
}
Insert(table_name, values) => {
let table: &mut Table = self.table_from_name_mut(&table_name)?;
@ -210,8 +211,8 @@ mod tests {
let response: Response = state
.interpret(Operation::Select(users.clone(), ColumnSelection::All, None))
.unwrap();
assert!(matches!(response, Response::Selected(_)));
let Response::Selected(rows) = response else {
assert!(matches!(response, Response::Selected(_, _)));
let Response::Selected(schema, rows) = response else {
panic!()
};
let rows: Vec<_> = rows.collect();
@ -263,8 +264,8 @@ mod tests {
.interpret(Operation::Select(users.clone(), ColumnSelection::All, None))
.unwrap();
assert!(matches!(response, Response::Selected(_)));
let Response::Selected(rows) = response else {
assert!(matches!(response, Response::Selected(_, _)));
let Response::Selected(schema, rows) = response else {
panic!()
};
let rows: Vec<_> = rows.collect();
@ -272,9 +273,9 @@ mod tests {
let row = &rows[0];
assert!(row.len() == 3);
assert!(row[0] == id);
assert!(row[1] == name);
assert!(row[2] == age);
assert!(row[0].1 == id);
assert!(row[1].1 == name);
assert!(row[2].1 == age);
}
#[test]
@ -328,24 +329,25 @@ mod tests {
{
let response: Response = state.interpret(Select(users.clone(), All, None)).unwrap();
assert!(matches!(response, Response::Selected(_)));
let Response::Selected(rows) = response else {
assert!(matches!(response, Response::Selected(_, _)));
let Response::Selected(_, rows) = response else {
panic!()
};
let rows: Vec<_> = rows.collect();
let rows: Vec<_> = rows.collect();
assert!(rows.len() == 2);
let row0 = &rows[0];
let row1 = &rows[1];
assert!(row0.len() == 3);
assert!(row0[0] == id0);
assert!(row0[1] == name0);
assert!(row0[2] == age0);
assert!(row0[0].1 == id0);
assert!(row0[1].1 == name0);
assert!(row0[2].1 == age0);
assert!(row1.len() == 3);
assert!(row1[0] == id1);
assert!(row1[1] == name1);
assert!(row1[2] == age1);
assert!(row1[0].1 == id1);
assert!(row1[1].1 == name1);
assert!(row1[2].1 == age1);
}
{
@ -356,8 +358,8 @@ mod tests {
Some(Eq("id".to_string(), id0.clone())),
))
.unwrap();
assert!(matches!(response, Response::Selected(_)));
let Response::Selected(rows) = response else {
assert!(matches!(response, Response::Selected(_, _)));
let Response::Selected(_, rows) = response else {
panic!()
};
let rows: Vec<_> = rows.collect();
@ -365,9 +367,9 @@ mod tests {
let row0 = &rows[0];
assert!(row0.len() == 3);
assert!(row0[0] == id0);
assert!(row0[1] == name0);
assert!(row0[2] == age0);
assert!(row0[0].1 == id0);
assert!(row0[1].1 == name0);
assert!(row0[2].1 == age0);
}
{
@ -378,8 +380,8 @@ mod tests {
Some(Eq("id".to_string(), id0.clone())),
))
.unwrap();
assert!(matches!(response, Response::Selected(_)));
let Response::Selected(rows) = response else {
assert!(matches!(response, Response::Selected(_, _)));
let Response::Selected(_, rows) = response else {
panic!()
};
let rows: Vec<_> = rows.collect();
@ -387,8 +389,8 @@ mod tests {
let row0 = &rows[0];
assert!(row0.len() == 2);
assert!(row0[0] == name0);
assert!(row0[1] == id0);
assert!(row0[0].1 == name0);
assert!(row0[1].1 == id0);
}
}
@ -452,8 +454,8 @@ mod tests {
let response: Response = state.interpret(Select(users.clone(), All, None)).unwrap();
assert!(matches!(response, Response::Selected(_)));
let Response::Selected(rows) = response else {
assert!(matches!(response, Response::Selected(_, _)));
let Response::Selected(_, rows) = response else {
panic!()
};
let rows: Vec<_> = rows.collect();
@ -461,9 +463,9 @@ mod tests {
let row = &rows[0];
assert!(row.len() == 3);
assert!(row[0] == id1);
assert!(row[1] == name1);
assert!(row[2] == age1);
assert!(row[0].1 == id1);
assert!(row[1].1 == name1);
assert!(row[2].1 == age1);
}
#[test]
@ -644,4 +646,4 @@ pub fn example() {
println!("{:?}", response);
println!();
}
}
}

View file

@ -5,3 +5,4 @@ pub mod type_system;
mod error;
mod internals;
mod result;
pub mod restricted_row;

View file

@ -0,0 +1,35 @@
use std::ops::Index;
use std::slice::SliceIndex;
use crate::internals::row::ColumnPosition;
use crate::type_system::Value;
#[derive(Debug, Clone)]
pub struct RestrictedRow(Vec<(ColumnPosition, Value)>);
impl<Idx> Index<Idx> for RestrictedRow
where
Idx: SliceIndex<[(ColumnPosition, Value)]>,
{
type Output = Idx::Output;
fn index(&self, index: Idx) -> &Self::Output {
&self.0[index]
}
}
impl From<Vec<(ColumnPosition, Value)>> for RestrictedRow {
fn from(v: Vec<(ColumnPosition, Value)>) -> Self {
RestrictedRow(v)
}
}
impl RestrictedRow {
pub fn len(&self) -> usize {
self.0.len()
}
pub fn iter(&self) -> impl Iterator<Item=&(ColumnPosition, Value)> {
self.0.iter()
}
}