Now interpreter returns an iterator
This commit is contained in:
parent
430d092def
commit
ddf17ae0a5
2 changed files with 88 additions and 59 deletions
|
|
@ -67,37 +67,40 @@ impl Table {
|
|||
.collect()
|
||||
}
|
||||
|
||||
pub fn select_all_rows(&self, selected_column_positions: &Vec<ColumnPosition>) -> Vec<Row> {
|
||||
pub fn select_all_rows<'a>(&'a self, selected_column_positions: Vec<ColumnPosition>) -> impl Iterator<Item=Row> + 'a {
|
||||
self.rows
|
||||
.values()
|
||||
.map(|row| row.restrict_columns(selected_column_positions))
|
||||
.collect()
|
||||
.map(move |row| row.restrict_columns(&selected_column_positions))
|
||||
}
|
||||
|
||||
pub fn select_rows_where_eq(
|
||||
&self,
|
||||
selected_column_positions: &Vec<ColumnPosition>,
|
||||
pub fn select_rows_where_eq<'a>(
|
||||
&'a self,
|
||||
selected_column_positions: Vec<ColumnPosition>,
|
||||
column_position: ColumnPosition,
|
||||
value: Value,
|
||||
) -> DbResult<Vec<Row>> {
|
||||
) -> DbResult<impl Iterator<Item=Row> + '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)? {
|
||||
Some(ids) => Ok(self
|
||||
Some(ids) =>
|
||||
Ok(self
|
||||
.get_rows_by_ids(ids)
|
||||
.iter()
|
||||
.map(|row| row.restrict_columns(selected_column_positions))
|
||||
.collect()),
|
||||
None => Ok(self
|
||||
.into_iter()
|
||||
.map(restrict_columns_of_row)
|
||||
),
|
||||
None =>
|
||||
Ok(self
|
||||
.get_rows_by_value(column_position, &Value::Indexable(value))
|
||||
.iter()
|
||||
.map(|row| row.restrict_columns(selected_column_positions))
|
||||
.collect()),
|
||||
.into_iter()
|
||||
.map(restrict_columns_of_row)
|
||||
),
|
||||
},
|
||||
_ => Ok(self
|
||||
_ =>
|
||||
Ok(self
|
||||
.get_rows_by_value(column_position, &value)
|
||||
.iter()
|
||||
.map(|row| row.restrict_columns(selected_column_positions))
|
||||
.collect()),
|
||||
.into_iter()
|
||||
.map(restrict_columns_of_row)
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,15 +18,35 @@ pub struct State {
|
|||
tables: Tables,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Response {
|
||||
Selected(Vec<Row>),
|
||||
// #[derive(Debug)]
|
||||
pub enum Response<'a> {
|
||||
Selected(Box<dyn Iterator<Item=Row> + 'a>),
|
||||
Inserted,
|
||||
Deleted(usize), // how many were deleted
|
||||
TableCreated,
|
||||
IndexCreated,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Response<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
use Response::*;
|
||||
match self {
|
||||
Selected(_rows) =>
|
||||
// TODO: How can we iterate through the rows without having to take ownership of
|
||||
// them?
|
||||
f.write_str("Some rows... trust me"),
|
||||
Inserted =>
|
||||
f.write_str("Inserted"),
|
||||
Deleted(usize) =>
|
||||
f.write_fmt(format_args!("Deleted({})", usize)),
|
||||
TableCreated =>
|
||||
f.write_str("TableCreated"),
|
||||
IndexCreated =>
|
||||
f.write_str("IndexCreated"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
|
|
@ -35,7 +55,7 @@ impl State {
|
|||
}
|
||||
}
|
||||
|
||||
fn table_from_name<'b: 'a, 'a>(&'b self, table_name: &TableName) -> DbResult<&'a Table> {
|
||||
fn table_from_name<'a>(&'a self, table_name: &TableName) -> DbResult<&'a Table> {
|
||||
match self.table_name_position_mapping.get_by_left(table_name) {
|
||||
Some(table_position) => {
|
||||
let table = &self.tables[*table_position];
|
||||
|
|
@ -65,13 +85,7 @@ impl State {
|
|||
self.tables.push(table);
|
||||
}
|
||||
|
||||
// TODO: Decide if we want for this to return a response (but then you have to deal with lifetimes,
|
||||
// because you'll be forced to put an iterator/slice into the Response data-structure.
|
||||
// Alternative is to pass a row-consumer to the functionas that knows how to communicate with
|
||||
// the client, but the details of communication are hidden behind an interface
|
||||
//
|
||||
// writer: impl SqlResponseConsumer
|
||||
pub fn interpret(&mut self, operation: Operation) -> DbResult<Response> {
|
||||
pub fn interpret<'a>(&'a mut self, operation: Operation) -> DbResult<Response<'a>> {
|
||||
// TODO: lock stuff
|
||||
use Operation::*;
|
||||
|
||||
|
|
@ -83,17 +97,22 @@ impl State {
|
|||
.schema()
|
||||
.column_positions_from_column_selection(&column_selection)?;
|
||||
let selected_rows = match maybe_condition {
|
||||
None => table.select_all_rows(&selected_column_positions),
|
||||
None => {
|
||||
let x = table.select_all_rows(selected_column_positions);
|
||||
Box::new(x) as Box<dyn Iterator<Item=Row> + 'a>
|
||||
},
|
||||
|
||||
Some(Condition::Eq(eq_column_name, value)) => {
|
||||
let eq_column_position = table
|
||||
.schema()
|
||||
.column_position_from_column_name(&eq_column_name)?;
|
||||
let x =
|
||||
table.select_rows_where_eq(
|
||||
&selected_column_positions,
|
||||
selected_column_positions,
|
||||
eq_column_position,
|
||||
value,
|
||||
)?
|
||||
)?;
|
||||
Box::new(x) as Box<dyn Iterator<Item=Row> + 'a>
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -140,11 +159,6 @@ impl State {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Give a better name to something that you can respond to with rows
|
||||
trait SqlResponseConsumer {
|
||||
// TODO:
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
@ -198,8 +212,9 @@ mod tests {
|
|||
.unwrap();
|
||||
assert!(matches!(response, Response::Selected(_)));
|
||||
let Response::Selected(rows) = response else {
|
||||
todo!()
|
||||
panic!()
|
||||
};
|
||||
let rows: Vec<_> = rows.collect();
|
||||
assert!(rows.len() == 0);
|
||||
}
|
||||
|
||||
|
|
@ -250,8 +265,9 @@ mod tests {
|
|||
|
||||
assert!(matches!(response, Response::Selected(_)));
|
||||
let Response::Selected(rows) = response else {
|
||||
todo!()
|
||||
panic!()
|
||||
};
|
||||
let rows: Vec<_> = rows.collect();
|
||||
assert!(rows.len() == 1);
|
||||
let row = &rows[0];
|
||||
|
||||
|
|
@ -314,8 +330,9 @@ mod tests {
|
|||
|
||||
assert!(matches!(response, Response::Selected(_)));
|
||||
let Response::Selected(rows) = response else {
|
||||
todo!()
|
||||
panic!()
|
||||
};
|
||||
let rows: Vec<_> = rows.collect();
|
||||
assert!(rows.len() == 2);
|
||||
let row0 = &rows[0];
|
||||
let row1 = &rows[1];
|
||||
|
|
@ -341,8 +358,9 @@ mod tests {
|
|||
.unwrap();
|
||||
assert!(matches!(response, Response::Selected(_)));
|
||||
let Response::Selected(rows) = response else {
|
||||
todo!()
|
||||
panic!()
|
||||
};
|
||||
let rows: Vec<_> = rows.collect();
|
||||
assert!(rows.len() == 1);
|
||||
let row0 = &rows[0];
|
||||
|
||||
|
|
@ -362,8 +380,9 @@ mod tests {
|
|||
.unwrap();
|
||||
assert!(matches!(response, Response::Selected(_)));
|
||||
let Response::Selected(rows) = response else {
|
||||
todo!()
|
||||
panic!()
|
||||
};
|
||||
let rows: Vec<_> = rows.collect();
|
||||
assert!(rows.len() == 1);
|
||||
let row0 = &rows[0];
|
||||
|
||||
|
|
@ -421,6 +440,7 @@ mod tests {
|
|||
))
|
||||
.unwrap();
|
||||
|
||||
{
|
||||
let delete_response: Response = state
|
||||
.interpret(Delete(
|
||||
users.clone(),
|
||||
|
|
@ -428,13 +448,15 @@ mod tests {
|
|||
))
|
||||
.unwrap();
|
||||
assert!(matches!(delete_response, Response::Deleted(1)));
|
||||
}
|
||||
|
||||
let response: Response = state.interpret(Select(users.clone(), All, None)).unwrap();
|
||||
|
||||
assert!(matches!(response, Response::Selected(_)));
|
||||
let Response::Selected(rows) = response else {
|
||||
todo!()
|
||||
panic!()
|
||||
};
|
||||
let rows: Vec<_> = rows.collect();
|
||||
assert!(rows.len() == 1);
|
||||
let row = &rows[0];
|
||||
|
||||
|
|
@ -600,6 +622,9 @@ pub fn example() {
|
|||
}
|
||||
|
||||
{
|
||||
{
|
||||
// TODO: Why do I have to write these braces explicitely? Why doesn't Rust compiler
|
||||
// "infer" them?
|
||||
let _delete_response: Response = state
|
||||
.interpret(Delete(
|
||||
users.clone(),
|
||||
|
|
@ -607,6 +632,7 @@ pub fn example() {
|
|||
))
|
||||
.unwrap();
|
||||
println!("==DELETE Plato==");
|
||||
}
|
||||
let response: Response = state
|
||||
.interpret(Select(
|
||||
users.clone(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue