This commit is contained in:
Yuriy Dupyn 2024-01-27 22:46:19 +01:00
parent 9771a89716
commit 11dc992476
10 changed files with 157 additions and 403 deletions

View file

@ -1,10 +1,8 @@
use crate::error::Error;
use crate::internals::row::{ColumnPosition, Row};
use crate::internals::row::Row;
use crate::schema::{TableName, TableSchema};
use crate::internals::table::Table;
use crate::operation::{ColumnSelection, Condition, Operation, OperationForInterpreter, ConditionForInterpreter};
use crate::operation::{Operation, Condition};
use crate::result::DbResult;
use crate::type_system::{DbType, IndexableValue, Value};
use bimap::BiMap;
// Use `TablePosition` as index
@ -57,7 +55,6 @@ impl State {
}
}
/// TODO: return a reference to avoid allocations
pub fn db_schema<'a>(&'a self) -> DbSchema {
let mut schema: DbSchema = Vec::new();
for (table_name, &table_position) in &self.table_name_position_mapping {
@ -67,34 +64,10 @@ impl State {
schema
}
// TODO: Get rid of this
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];
Ok(table)
}
None => Err(Error::TableDoesNotExist(table_name.clone())),
}
}
fn table_at<'a>(&'a self, table_position: TablePosition) -> &'a Table {
&self.tables[table_position]
}
fn table_from_name_mut<'b: 'a, 'a>(
&'b mut self,
table_name: &TableName,
) -> DbResult<&'a mut Table> {
match self.table_name_position_mapping.get_by_left(table_name) {
Some(table_position) => {
let table = &mut self.tables[*table_position];
Ok(table)
}
None => Err(Error::TableDoesNotExist(table_name.clone())),
}
}
fn table_at_mut<'a>(&'a mut self, table_position: TablePosition) -> &'a mut Table {
&mut self.tables[table_position]
}
@ -106,9 +79,9 @@ impl State {
self.tables.push(table);
}
pub fn interpret_for_interpreter<'a>(&'a mut self, operation: OperationForInterpreter) -> DbResult<Response<'a>> {
pub fn interpret<'a>(&'a mut self, operation: Operation) -> DbResult<Response<'a>> {
// TODO: lock stuff
use OperationForInterpreter::*;
use Operation::*;
match operation {
Select(table_position, column_selection, maybe_condition) => {
@ -120,7 +93,7 @@ impl State {
Box::new(x) as Box<dyn Iterator<Item=Row> + 'a + Send>
},
Some(ConditionForInterpreter::Eq(eq_column, value)) => {
Some(Condition::Eq(eq_column, value)) => {
let x =
table.select_rows_where_eq(
column_selection,
@ -136,7 +109,7 @@ impl State {
Insert(table_position, values) => {
let table: &mut Table = self.table_at_mut(table_position);
let (id, row) = table.schema().row_from_insertion_values_for_interpreter(values)?;
let (id, row) = table.schema().row_from_insertion_values(values)?;
table.insert_row_at(id, row)?;
Ok(Response::Inserted)
}
@ -145,7 +118,7 @@ impl State {
let rows_affected = match maybe_condition {
None => table.delete_all_rows(),
Some(ConditionForInterpreter::Eq(eq_column, value)) => {
Some(Condition::Eq(eq_column, value)) => {
table.delete_rows_where_eq(eq_column, value)?
}
};
@ -165,85 +138,15 @@ impl State {
}
}
}
pub fn interpret<'a>(&'a mut self, operation: Operation) -> DbResult<Response<'a>> {
// TODO: lock stuff
use Operation::*;
match operation {
Select(table_name, column_selection, maybe_condition) => {
let table: &Table = self.table_from_name(&table_name)?;
let selected_column_positions: Vec<ColumnPosition> = table
.schema()
.column_positions_from_column_selection(&column_selection)?;
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 + Send>
},
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,
eq_column_position,
value,
)?;
Box::new(x) as Box<dyn Iterator<Item=Row> + 'a + Send>
}
};
Ok(Response::Selected(selected_rows))
}
Insert(table_name, values) => {
let table: &mut Table = self.table_from_name_mut(&table_name)?;
let (id, row) = table.schema().row_from_insertion_values(values)?;
table.insert_row_at(id, row)?;
Ok(Response::Inserted)
}
Delete(table_name, maybe_condition) => {
let table: &mut Table = self.table_from_name_mut(&table_name)?;
let rows_affected = match maybe_condition {
None => table.delete_all_rows(),
Some(Condition::Eq(eq_column_name, value)) => {
let eq_column_position = table
.schema()
.column_position_from_column_name(&eq_column_name)?;
table.delete_rows_where_eq(eq_column_position, value)?
}
};
Ok(Response::Deleted(rows_affected))
}
CreateTable(table_name, table_schema) => {
let table = Table::new(table_schema);
self.attach_table(table_name, table);
Ok(Response::TableCreated)
}
CreateIndex(table_name, column_name) => {
let table: &mut Table = self.table_from_name_mut(&table_name)?;
let column_position: ColumnPosition = table
.schema()
.column_position_from_column_name(&column_name)?;
table.attach_index(column_position)?;
Ok(Response::IndexCreated)
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::internals::row::ColumnPosition;
use std::collections::HashSet;
use crate::type_system::{DbType, IndexableValue, Value};
use crate::operation::Operation;
fn users_schema() -> TableSchema {
let id: ColumnPosition = 0;
@ -284,12 +187,13 @@ mod tests {
let mut state = State::new();
let users_schema = users_schema();
let users = users_schema.table_name().clone();
let users_position = 0;
state
.interpret(Operation::CreateTable(users.clone(), users_schema))
.interpret(Operation::CreateTable(users, users_schema.clone()))
.unwrap();
let response: Response = state
.interpret(Operation::Select(users.clone(), ColumnSelection::All, None))
.interpret(Operation::Select(users_position, users_schema.all_selection(), None))
.unwrap();
assert!(matches!(response, Response::Selected(_)));
let Response::Selected(rows) = response else {
@ -299,18 +203,6 @@ mod tests {
assert!(rows.len() == 0);
}
#[test]
fn test_select_nonexistant_table() {
let mut state = State::new();
let response: DbResult<Response> = state.interpret(Operation::Select(
"table_that_doesnt_exist".to_string(),
ColumnSelection::All,
None,
));
assert!(matches!(response, Err(Error::TableDoesNotExist(_))));
}
#[test]
fn test_insert_select_basic1() {
use IndexableValue::*;
@ -318,10 +210,11 @@ mod tests {
let mut state = State::new();
let users_schema = users_schema();
let users = users_schema.table_name().clone();
let users = 0;
state
.interpret(Operation::CreateTable(users.clone(), users_schema))
.interpret(Operation::CreateTable("users".to_string(), users_schema.clone()))
.unwrap();
let (id, name, age) = (
@ -331,17 +224,17 @@ mod tests {
);
state
.interpret(Operation::Insert(
users.clone(),
users,
vec![
("id".to_string(), id.clone()),
("name".to_string(), name.clone()),
("age".to_string(), age.clone()),
id.clone(),
name.clone(),
age.clone(),
],
))
.unwrap();
let response: Response = state
.interpret(Operation::Select(users.clone(), ColumnSelection::All, None))
.interpret(Operation::Select(users, users_schema.all_selection(), None))
.unwrap();
assert!(matches!(response, Response::Selected(_)));
@ -351,7 +244,7 @@ mod tests {
let rows: Vec<_> = rows.collect();
assert!(rows.len() == 1);
let row = &rows[0];
assert!(row.len() == 3);
assert!(row[0] == id);
assert!(row[1] == name);
@ -360,7 +253,6 @@ mod tests {
#[test]
fn test_insert_select_basic2() {
use ColumnSelection::*;
use Condition::*;
use IndexableValue::*;
use Operation::*;
@ -368,10 +260,13 @@ mod tests {
let mut state = State::new();
let users_schema = users_schema();
let users = users_schema.table_name().clone();
let users_position: TablePosition = 0;
let id_column: ColumnPosition = 0;
let name_column: ColumnPosition = 1;
state
.interpret(CreateTable(users.clone(), users_schema))
.interpret(CreateTable(users_schema.table_name().clone(), users_schema.clone()))
.unwrap();
let (id0, name0, age0) = (
@ -381,11 +276,11 @@ mod tests {
);
state
.interpret(Insert(
users.clone(),
users_position,
vec![
("id".to_string(), id0.clone()),
("name".to_string(), name0.clone()),
("age".to_string(), age0.clone()),
id0.clone(),
name0.clone(),
age0.clone(),
],
))
.unwrap();
@ -397,17 +292,17 @@ mod tests {
);
state
.interpret(Insert(
users.clone(),
users_position,
vec![
("id".to_string(), id1.clone()),
("name".to_string(), name1.clone()),
("age".to_string(), age1.clone()),
id1.clone(),
name1.clone(),
age1.clone(),
],
))
.unwrap();
{
let response: Response = state.interpret(Select(users.clone(), All, None)).unwrap();
let response: Response = state.interpret(Select(users_position, users_schema.all_selection(), None)).unwrap();
assert!(matches!(response, Response::Selected(_)));
let Response::Selected(rows) = response else {
@ -432,9 +327,9 @@ mod tests {
{
let response: Response = state
.interpret(Select(
users.clone(),
All,
Some(Eq("id".to_string(), id0.clone())),
users_position,
users_schema.all_selection(),
Some(Eq(id_column, id0.clone())),
))
.unwrap();
assert!(matches!(response, Response::Selected(_)));
@ -454,9 +349,9 @@ mod tests {
{
let response: Response = state
.interpret(Select(
users.clone(),
Columns(vec!["name".to_string(), "id".to_string()]),
Some(Eq("id".to_string(), id0.clone())),
users_position,
vec![name_column, id_column],
Some(Eq(id_column, id0.clone())),
))
.unwrap();
assert!(matches!(response, Response::Selected(_)));
@ -475,7 +370,6 @@ mod tests {
#[test]
fn test_delete() {
use ColumnSelection::*;
use Condition::*;
use IndexableValue::*;
use Operation::*;
@ -483,10 +377,12 @@ mod tests {
let mut state = State::new();
let users_schema = users_schema();
let users = users_schema.table_name().clone();
let users_position: TablePosition = 0;
let id_column: ColumnPosition = 0;
state
.interpret(CreateTable(users.clone(), users_schema))
.interpret(CreateTable(users_schema.table_name().clone(), users_schema.clone()))
.unwrap();
let (id0, name0, age0) = (
@ -496,11 +392,11 @@ mod tests {
);
state
.interpret(Insert(
users.clone(),
users_position,
vec![
("id".to_string(), id0.clone()),
("name".to_string(), name0.clone()),
("age".to_string(), age0.clone()),
id0.clone(),
name0.clone(),
age0.clone(),
],
))
.unwrap();
@ -512,11 +408,11 @@ mod tests {
);
state
.interpret(Insert(
users.clone(),
users_position,
vec![
("id".to_string(), id1.clone()),
("name".to_string(), name1.clone()),
("age".to_string(), age1.clone()),
id1.clone(),
name1.clone(),
age1.clone(),
],
))
.unwrap();
@ -524,14 +420,14 @@ mod tests {
{
let delete_response: Response = state
.interpret(Delete(
users.clone(),
Some(Eq("id".to_string(), id0.clone())),
users_position,
Some(Eq(id_column, id0.clone())),
))
.unwrap();
assert!(matches!(delete_response, Response::Deleted(1)));
}
let response: Response = state.interpret(Select(users.clone(), All, None)).unwrap();
let response: Response = state.interpret(Select(users_position, users_schema.all_selection(), None)).unwrap();
assert!(matches!(response, Response::Selected(_)));
let Response::Selected(rows) = response else {
@ -555,14 +451,16 @@ mod tests {
let mut state = State::new();
let users_schema = users_schema();
let users = users_schema.table_name().clone();
let users_position: TablePosition = 0;
let name_column: ColumnPosition = 1;
state
.interpret(CreateTable(users.clone(), users_schema))
.interpret(CreateTable(users_schema.table_name().clone(), users_schema.clone()))
.unwrap();
state
.interpret(CreateIndex(users.clone(), "name".to_string()))
.interpret(CreateIndex(users_position, name_column))
.unwrap();
let (id0, name0, age0) = (
@ -572,11 +470,11 @@ mod tests {
);
state
.interpret(Insert(
users.clone(),
users_position,
vec![
("id".to_string(), id0.clone()),
("name".to_string(), name0.clone()),
("age".to_string(), age0.clone()),
id0.clone(),
name0.clone(),
age0.clone(),
],
))
.unwrap();
@ -588,11 +486,11 @@ mod tests {
);
state
.interpret(Insert(
users.clone(),
users_position,
vec![
("id".to_string(), id1.clone()),
("name".to_string(), name1.clone()),
("age".to_string(), age1.clone()),
id1.clone(),
name1.clone(),
age1.clone(),
],
))
.unwrap();
@ -617,33 +515,35 @@ mod tests {
}
pub fn example() {
use ColumnSelection::*;
use crate::type_system::{IndexableValue, Value, DbType};
use crate::internals::row::ColumnPosition;
use Condition::*;
use IndexableValue::*;
use Operation::*;
use Value::*;
let users_schema: TableSchema = {
let id: ColumnPosition = 0;
let name: ColumnPosition = 1;
let age: ColumnPosition = 2;
let id_column: ColumnPosition = 0;
let name_column: ColumnPosition = 1;
let age_column: ColumnPosition = 2;
let users_schema: TableSchema = {
TableSchema::new(
"users".to_string(),
id,
id_column,
vec!(
("id".to_string(), id),
("name".to_string(), name),
("age".to_string(), age),
("id".to_string(), id_column),
("name".to_string(), name_column),
("age".to_string(), age_column),
),
vec![DbType::Uuid, DbType::String, DbType::Int],
)
};
let users_position: TablePosition = 0;
let users = users_schema.table_name().clone();
let mut state = State::new();
state
.interpret(Operation::CreateTable(users.clone(), users_schema))
.interpret(Operation::CreateTable(users, users_schema.clone()))
.unwrap();
let (id0, name0, age0) = (
@ -654,11 +554,11 @@ pub fn example() {
println!("==INSERT Plato==");
state
.interpret(Insert(
users.clone(),
users_position,
vec![
("id".to_string(), id0.clone()),
("name".to_string(), name0.clone()),
("age".to_string(), age0.clone()),
id0.clone(),
name0.clone(),
age0.clone(),
],
))
.unwrap();
@ -671,11 +571,11 @@ pub fn example() {
println!("==INSERT Aristotle==");
state
.interpret(Insert(
users.clone(),
users_position,
vec![
("id".to_string(), id1.clone()),
("name".to_string(), name1.clone()),
("age".to_string(), age1.clone()),
id1.clone(),
name1.clone(),
age1.clone(),
],
))
.unwrap();
@ -683,7 +583,7 @@ pub fn example() {
{
let response: Response = state
.interpret(Operation::Select(users.clone(), ColumnSelection::All, None))
.interpret(Operation::Select(users_position, users_schema.all_selection(), None))
.unwrap();
println!("==SELECT ALL==");
println!("{:?}", response);
@ -692,9 +592,9 @@ pub fn example() {
{
let response: Response = state
.interpret(Select(
users.clone(),
All,
Some(Eq("id".to_string(), id0.clone())),
users_position,
users_schema.all_selection(),
Some(Eq(id_column, id0.clone())),
))
.unwrap();
println!("==SELECT Plato==");
@ -708,16 +608,16 @@ pub fn example() {
// "infer" them?
let _delete_response: Response = state
.interpret(Delete(
users.clone(),
Some(Eq("id".to_string(), id0.clone())),
users_position,
Some(Eq(id_column, id0.clone())),
))
.unwrap();
println!("==DELETE Plato==");
}
let response: Response = state
.interpret(Select(
users.clone(),
Columns(vec!["name".to_string(), "id".to_string()]),
users_position,
vec![name_column, id_column],
None,
))
.unwrap();