feat: return schema and column positions with select
This commit is contained in:
parent
ebabf50291
commit
1d746430d2
5 changed files with 84 additions and 43 deletions
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)? {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
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]
|
||||
|
|
|
|||
|
|
@ -5,3 +5,4 @@ pub mod type_system;
|
|||
mod error;
|
||||
mod internals;
|
||||
mod result;
|
||||
pub mod restricted_row;
|
||||
|
|
|
|||
35
minisql/src/restricted_row.rs
Normal file
35
minisql/src/restricted_row.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue