cargo format
This commit is contained in:
parent
4d45da0cd1
commit
845db102c2
33 changed files with 885 additions and 530 deletions
|
|
@ -1,8 +1,8 @@
|
|||
use crate::schema::{ColumnName, TableName};
|
||||
use crate::type_system::Uuid;
|
||||
use std::num::{ParseFloatError, ParseIntError};
|
||||
use std::str::Utf8Error;
|
||||
use thiserror::Error;
|
||||
use crate::schema::{ColumnName, TableName};
|
||||
use crate::type_system::Uuid;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum RuntimeError {
|
||||
|
|
@ -23,8 +23,5 @@ pub enum TypeConversionError {
|
|||
#[error("failed to parse int from text")]
|
||||
IntDecodeFailed(#[from] ParseIntError),
|
||||
#[error("unknown type with oid {oid} and size {size}")]
|
||||
UnknownType {
|
||||
oid: i32,
|
||||
size: i16
|
||||
}
|
||||
UnknownType { oid: i32, size: i16 },
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::type_system::{IndexableValue, Uuid};
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ColumnIndex {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use crate::type_system::Value;
|
||||
use crate::operation::InsertionValues;
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::slice::SliceIndex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::restricted_row::RestrictedRow;
|
||||
use crate::schema::Column;
|
||||
use crate::type_system::Value;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::slice::SliceIndex;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Row(Vec<Value>);
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
|
||||
use crate::error::RuntimeError;
|
||||
use crate::internals::column_index::ColumnIndex;
|
||||
use crate::internals::row::Row;
|
||||
use crate::restricted_row::RestrictedRow;
|
||||
use crate::schema::{Column, ColumnName, TableSchema, TableName};
|
||||
use crate::result::DbResult;
|
||||
use crate::schema::{Column, ColumnName, TableName, TableSchema};
|
||||
use crate::type_system::{IndexableValue, Uuid, Value};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
|
|
@ -69,7 +69,10 @@ impl Table {
|
|||
.collect()
|
||||
}
|
||||
|
||||
pub fn select_all_rows(&self, selected_columns: Vec<Column>) -> impl Iterator<Item=RestrictedRow> + '_ {
|
||||
pub fn select_all_rows(
|
||||
&self,
|
||||
selected_columns: Vec<Column>,
|
||||
) -> impl Iterator<Item = RestrictedRow> + '_ {
|
||||
self.rows
|
||||
.values()
|
||||
.map(move |row| row.restrict_columns(&selected_columns))
|
||||
|
|
@ -80,29 +83,23 @@ impl Table {
|
|||
selected_columns: Vec<Column>,
|
||||
column: Column,
|
||||
value: Value,
|
||||
) -> DbResult<impl Iterator<Item=RestrictedRow> + '_> {
|
||||
) -> DbResult<impl Iterator<Item = RestrictedRow> + '_> {
|
||||
let restrict_columns_of_row = move |row: Row| row.restrict_columns(&selected_columns);
|
||||
match value {
|
||||
Value::Indexable(value) => match self.fetch_ids_from_index(column, &value)? {
|
||||
Some(ids) =>
|
||||
Ok(self
|
||||
.get_rows_by_ids(ids)
|
||||
.into_iter()
|
||||
.map(restrict_columns_of_row)
|
||||
),
|
||||
None =>
|
||||
Ok(self
|
||||
.get_rows_by_value(column, &Value::Indexable(value))
|
||||
.into_iter()
|
||||
.map(restrict_columns_of_row)
|
||||
),
|
||||
},
|
||||
_ =>
|
||||
Ok(self
|
||||
.get_rows_by_value(column, &value)
|
||||
Some(ids) => Ok(self
|
||||
.get_rows_by_ids(ids)
|
||||
.into_iter()
|
||||
.map(restrict_columns_of_row)
|
||||
),
|
||||
.map(restrict_columns_of_row)),
|
||||
None => Ok(self
|
||||
.get_rows_by_value(column, &Value::Indexable(value))
|
||||
.into_iter()
|
||||
.map(restrict_columns_of_row)),
|
||||
},
|
||||
_ => Ok(self
|
||||
.get_rows_by_value(column, &value)
|
||||
.into_iter()
|
||||
.map(restrict_columns_of_row)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -116,7 +113,9 @@ impl Table {
|
|||
}
|
||||
|
||||
for (column, column_index) in &mut self.indexes {
|
||||
if let Value::Indexable(val) = &row[*column] { column_index.add(val.clone(), id) }
|
||||
if let Value::Indexable(val) = &row[*column] {
|
||||
column_index.add(val.clone(), id)
|
||||
}
|
||||
}
|
||||
|
||||
let _ = self.rows.insert(id, row);
|
||||
|
|
@ -168,11 +167,7 @@ impl Table {
|
|||
number_of_rows
|
||||
}
|
||||
|
||||
pub fn delete_rows_where_eq(
|
||||
&mut self,
|
||||
column: Column,
|
||||
value: Value,
|
||||
) -> DbResult<usize> {
|
||||
pub fn delete_rows_where_eq(&mut self, column: Column, value: Value) -> DbResult<usize> {
|
||||
match value {
|
||||
Value::Indexable(value) => match self.fetch_ids_from_index(column, &value)? {
|
||||
Some(ids) => Ok(self.delete_rows_by_ids(ids)),
|
||||
|
|
@ -187,7 +182,10 @@ impl Table {
|
|||
if self.indexes.get(&column).is_some() {
|
||||
let column_name = self.schema.column_name_from_column(column).clone();
|
||||
let table_name = self.schema.table_name().clone();
|
||||
return Err(RuntimeError::AttemptToIndexAlreadyIndexedColumn(table_name, column_name))
|
||||
return Err(RuntimeError::AttemptToIndexAlreadyIndexedColumn(
|
||||
table_name,
|
||||
column_name,
|
||||
));
|
||||
}
|
||||
let mut column_index: ColumnIndex = ColumnIndex::new();
|
||||
update_index_from_table(&mut column_index, self, column)?;
|
||||
|
|
@ -203,7 +201,7 @@ impl Table {
|
|||
if self.schema.is_primary(column) {
|
||||
match value {
|
||||
IndexableValue::Uuid(id) => Ok(Some(HashSet::from([*id]))),
|
||||
_ => unreachable!() // SAFETY: Validation guarantees primary column has correct Uuid type.
|
||||
_ => unreachable!(), // SAFETY: Validation guarantees primary column has correct Uuid type.
|
||||
}
|
||||
} else {
|
||||
match self.indexes.get(&column) {
|
||||
|
|
@ -231,9 +229,7 @@ fn update_index_from_table(
|
|||
let value = match &row[column] {
|
||||
Value::Indexable(value) => value.clone(),
|
||||
_ => {
|
||||
let column_name: ColumnName = table
|
||||
.schema
|
||||
.column_name_from_column(column);
|
||||
let column_name: ColumnName = table.schema.column_name_from_column(column);
|
||||
return Err(RuntimeError::AttemptToIndexNonIndexableColumn(
|
||||
table.table_name().to_string(),
|
||||
column_name,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use crate::schema::{Column, TableName, TablePosition, TableSchema};
|
||||
use crate::internals::table::Table;
|
||||
use crate::operation::{Operation, Condition, ColumnSelection};
|
||||
use crate::operation::{ColumnSelection, Condition, Operation};
|
||||
use crate::restricted_row::RestrictedRow;
|
||||
use crate::result::DbResult;
|
||||
use crate::schema::{Column, TableName, TablePosition, TableSchema};
|
||||
use bimap::BiMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::restricted_row::RestrictedRow;
|
||||
|
||||
// Use `TablePosition` as index
|
||||
pub type Tables = Vec<Table>;
|
||||
|
|
@ -18,7 +18,11 @@ pub struct State {
|
|||
|
||||
// #[derive(Debug)]
|
||||
pub enum Response<'a> {
|
||||
Selected(&'a TableSchema, ColumnSelection, Box<dyn Iterator<Item=RestrictedRow> + 'a + Send>),
|
||||
Selected(
|
||||
&'a TableSchema,
|
||||
ColumnSelection,
|
||||
Box<dyn Iterator<Item = RestrictedRow> + 'a + Send>,
|
||||
),
|
||||
Inserted,
|
||||
Deleted(usize), // how many were deleted
|
||||
TableCreated,
|
||||
|
|
@ -32,17 +36,15 @@ impl std::fmt::Debug for Response<'_> {
|
|||
use Response::*;
|
||||
match self {
|
||||
Selected(_schema, _columns, _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"),
|
||||
// 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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -97,22 +99,25 @@ impl State {
|
|||
let selected_rows = match maybe_condition {
|
||||
None => {
|
||||
let rows = table.select_all_rows(column_selection.clone());
|
||||
Box::new(rows) as Box<dyn Iterator<Item=RestrictedRow> + 'a + Send>
|
||||
},
|
||||
Box::new(rows) as Box<dyn Iterator<Item = RestrictedRow> + 'a + Send>
|
||||
}
|
||||
|
||||
Some(Condition::Eq(eq_column, value)) => {
|
||||
let x =
|
||||
table.select_rows_where_eq(
|
||||
column_selection.clone(),
|
||||
eq_column,
|
||||
value,
|
||||
)?;
|
||||
Box::new(x) as Box<dyn Iterator<Item=RestrictedRow> + 'a + Send>
|
||||
let rows = table.select_rows_where_eq(
|
||||
column_selection.clone(),
|
||||
eq_column,
|
||||
value,
|
||||
)?;
|
||||
Box::new(rows) as Box<dyn Iterator<Item = RestrictedRow> + 'a + Send>
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Response::Selected(table.schema(), column_selection, selected_rows))
|
||||
},
|
||||
Ok(Response::Selected(
|
||||
table.schema(),
|
||||
column_selection,
|
||||
selected_rows,
|
||||
))
|
||||
}
|
||||
Insert(table_position, values) => {
|
||||
let table: &mut Table = self.table_at_mut(table_position);
|
||||
|
||||
|
|
@ -150,20 +155,16 @@ impl State {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::schema::Column;
|
||||
use std::collections::HashSet;
|
||||
use crate::type_system::{DbType, IndexableValue, Value};
|
||||
use crate::operation::Operation;
|
||||
use crate::schema::Column;
|
||||
use crate::type_system::{DbType, IndexableValue, Value};
|
||||
use std::collections::HashSet;
|
||||
|
||||
fn users_schema() -> TableSchema {
|
||||
TableSchema::new(
|
||||
"users".to_string(),
|
||||
"id".to_string(),
|
||||
vec!(
|
||||
"id".to_string(),
|
||||
"name".to_string(),
|
||||
"age".to_string(),
|
||||
),
|
||||
vec!["id".to_string(), "name".to_string(), "age".to_string()],
|
||||
vec![DbType::Uuid, DbType::String, DbType::Int],
|
||||
)
|
||||
}
|
||||
|
|
@ -195,7 +196,11 @@ mod tests {
|
|||
.interpret(Operation::CreateTable(users_schema.clone()))
|
||||
.unwrap();
|
||||
let response: Response = state
|
||||
.interpret(Operation::Select(users_position, users_schema.all_selection(), None))
|
||||
.interpret(Operation::Select(
|
||||
users_position,
|
||||
users_schema.all_selection(),
|
||||
None,
|
||||
))
|
||||
.unwrap();
|
||||
assert!(matches!(response, Response::Selected(_, _, _)));
|
||||
let Response::Selected(_, _, rows) = response else {
|
||||
|
|
@ -214,7 +219,6 @@ mod tests {
|
|||
let users_schema = users_schema();
|
||||
let users = 0;
|
||||
|
||||
|
||||
state
|
||||
.interpret(Operation::CreateTable(users_schema.clone()))
|
||||
.unwrap();
|
||||
|
|
@ -227,11 +231,7 @@ mod tests {
|
|||
state
|
||||
.interpret(Operation::Insert(
|
||||
users,
|
||||
vec![
|
||||
id.clone(),
|
||||
name.clone(),
|
||||
age.clone(),
|
||||
],
|
||||
vec![id.clone(), name.clone(), age.clone()],
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
|
|
@ -246,7 +246,7 @@ mod tests {
|
|||
let rows: Vec<_> = rows.collect();
|
||||
assert!(rows.len() == 1);
|
||||
let row = &rows[0];
|
||||
|
||||
|
||||
assert!(row.len() == 3);
|
||||
assert!(row[0].1 == id);
|
||||
assert!(row[1].1 == name);
|
||||
|
|
@ -267,9 +267,7 @@ mod tests {
|
|||
let id_column: Column = 0;
|
||||
let name_column: Column = 1;
|
||||
|
||||
state
|
||||
.interpret(CreateTable(users_schema.clone()))
|
||||
.unwrap();
|
||||
state.interpret(CreateTable(users_schema.clone())).unwrap();
|
||||
|
||||
let (id0, name0, age0) = (
|
||||
Indexable(Uuid(0)),
|
||||
|
|
@ -279,11 +277,7 @@ mod tests {
|
|||
state
|
||||
.interpret(Insert(
|
||||
users_position,
|
||||
vec![
|
||||
id0.clone(),
|
||||
name0.clone(),
|
||||
age0.clone(),
|
||||
],
|
||||
vec![id0.clone(), name0.clone(), age0.clone()],
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
|
|
@ -294,17 +288,15 @@ mod tests {
|
|||
);
|
||||
state
|
||||
.interpret(Insert(
|
||||
users_position,
|
||||
vec![
|
||||
id1.clone(),
|
||||
name1.clone(),
|
||||
age1.clone(),
|
||||
],
|
||||
users_position,
|
||||
vec![id1.clone(), name1.clone(), age1.clone()],
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
{
|
||||
let response: Response = state.interpret(Select(users_position, users_schema.all_selection(), 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 {
|
||||
|
|
@ -384,9 +376,7 @@ mod tests {
|
|||
|
||||
let id_column: Column = 0;
|
||||
|
||||
state
|
||||
.interpret(CreateTable(users_schema.clone()))
|
||||
.unwrap();
|
||||
state.interpret(CreateTable(users_schema.clone())).unwrap();
|
||||
|
||||
let (id0, name0, age0) = (
|
||||
Indexable(Uuid(0)),
|
||||
|
|
@ -396,11 +386,7 @@ mod tests {
|
|||
state
|
||||
.interpret(Insert(
|
||||
users_position,
|
||||
vec![
|
||||
id0.clone(),
|
||||
name0.clone(),
|
||||
age0.clone(),
|
||||
],
|
||||
vec![id0.clone(), name0.clone(), age0.clone()],
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
|
|
@ -412,25 +398,20 @@ mod tests {
|
|||
state
|
||||
.interpret(Insert(
|
||||
users_position,
|
||||
vec![
|
||||
id1.clone(),
|
||||
name1.clone(),
|
||||
age1.clone(),
|
||||
],
|
||||
vec![id1.clone(), name1.clone(), age1.clone()],
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
{
|
||||
let delete_response: Response = state
|
||||
.interpret(Delete(
|
||||
users_position,
|
||||
Some(Eq(id_column, id0.clone())),
|
||||
))
|
||||
.interpret(Delete(users_position, Some(Eq(id_column, id0.clone()))))
|
||||
.unwrap();
|
||||
assert!(matches!(delete_response, Response::Deleted(1)));
|
||||
}
|
||||
|
||||
let response: Response = state.interpret(Select(users_position, users_schema.all_selection(), 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 {
|
||||
|
|
@ -458,9 +439,7 @@ mod tests {
|
|||
|
||||
let name_column: Column = 1;
|
||||
|
||||
state
|
||||
.interpret(CreateTable(users_schema.clone()))
|
||||
.unwrap();
|
||||
state.interpret(CreateTable(users_schema.clone())).unwrap();
|
||||
|
||||
state
|
||||
.interpret(CreateIndex(users_position, name_column))
|
||||
|
|
@ -474,11 +453,7 @@ mod tests {
|
|||
state
|
||||
.interpret(Insert(
|
||||
users_position,
|
||||
vec![
|
||||
id0.clone(),
|
||||
name0.clone(),
|
||||
age0.clone(),
|
||||
],
|
||||
vec![id0.clone(), name0.clone(), age0.clone()],
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
|
|
@ -490,11 +465,7 @@ mod tests {
|
|||
state
|
||||
.interpret(Insert(
|
||||
users_position,
|
||||
vec![
|
||||
id1.clone(),
|
||||
name1.clone(),
|
||||
age1.clone(),
|
||||
],
|
||||
vec![id1.clone(), name1.clone(), age1.clone()],
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
|
|
@ -510,7 +481,10 @@ mod tests {
|
|||
let plato_id = 0;
|
||||
let aristotle_id = 1;
|
||||
|
||||
let plato_ids = index.get(&String("Plato".to_string())).cloned().unwrap_or(HashSet::new());
|
||||
let plato_ids = index
|
||||
.get(&String("Plato".to_string()))
|
||||
.cloned()
|
||||
.unwrap_or(HashSet::new());
|
||||
assert!(plato_ids.contains(&plato_id));
|
||||
assert!(!plato_ids.contains(&aristotle_id));
|
||||
assert!(plato_ids.len() == 1);
|
||||
|
|
@ -518,7 +492,7 @@ mod tests {
|
|||
}
|
||||
|
||||
pub fn example() {
|
||||
use crate::type_system::{IndexableValue, Value, DbType};
|
||||
use crate::type_system::{DbType, IndexableValue, Value};
|
||||
use Condition::*;
|
||||
use IndexableValue::*;
|
||||
use Operation::*;
|
||||
|
|
@ -532,11 +506,11 @@ pub fn example() {
|
|||
TableSchema::new(
|
||||
"users".to_string(),
|
||||
"id".to_string(),
|
||||
vec!(
|
||||
"id".to_string(), // 0
|
||||
vec![
|
||||
"id".to_string(), // 0
|
||||
"name".to_string(), // 1
|
||||
"age".to_string(), // 2
|
||||
),
|
||||
"age".to_string(), // 2
|
||||
],
|
||||
vec![DbType::Uuid, DbType::String, DbType::Int],
|
||||
)
|
||||
};
|
||||
|
|
@ -556,11 +530,7 @@ pub fn example() {
|
|||
state
|
||||
.interpret(Insert(
|
||||
users_position,
|
||||
vec![
|
||||
id0.clone(),
|
||||
name0.clone(),
|
||||
age0.clone(),
|
||||
],
|
||||
vec![id0.clone(), name0.clone(), age0.clone()],
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
|
|
@ -573,18 +543,18 @@ pub fn example() {
|
|||
state
|
||||
.interpret(Insert(
|
||||
users_position,
|
||||
vec![
|
||||
id1.clone(),
|
||||
name1.clone(),
|
||||
age1.clone(),
|
||||
],
|
||||
vec![id1.clone(), name1.clone(), age1.clone()],
|
||||
))
|
||||
.unwrap();
|
||||
println!();
|
||||
|
||||
{
|
||||
let response: Response = state
|
||||
.interpret(Operation::Select(users_position, users_schema.all_selection(), None))
|
||||
.interpret(Operation::Select(
|
||||
users_position,
|
||||
users_schema.all_selection(),
|
||||
None,
|
||||
))
|
||||
.unwrap();
|
||||
println!("==SELECT ALL==");
|
||||
println!("{:?}", response);
|
||||
|
|
@ -608,19 +578,12 @@ 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_position,
|
||||
Some(Eq(id_column, id0.clone())),
|
||||
))
|
||||
.unwrap();
|
||||
.interpret(Delete(users_position, Some(Eq(id_column, id0.clone()))))
|
||||
.unwrap();
|
||||
println!("==DELETE Plato==");
|
||||
}
|
||||
let response: Response = state
|
||||
.interpret(Select(
|
||||
users_position,
|
||||
vec![name_column, id_column],
|
||||
None,
|
||||
))
|
||||
.interpret(Select(users_position, vec![name_column, id_column], None))
|
||||
.unwrap();
|
||||
println!("==SELECT All==");
|
||||
println!("{:?}", response);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
pub mod schema;
|
||||
pub mod interpreter;
|
||||
pub mod operation;
|
||||
pub mod type_system;
|
||||
mod error;
|
||||
mod internals;
|
||||
mod result;
|
||||
pub mod interpreter;
|
||||
pub mod operation;
|
||||
pub mod restricted_row;
|
||||
mod result;
|
||||
pub mod schema;
|
||||
pub mod type_system;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::ops::Index;
|
||||
use std::slice::SliceIndex;
|
||||
use crate::schema::Column;
|
||||
use crate::type_system::Value;
|
||||
use std::ops::Index;
|
||||
use std::slice::SliceIndex;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RestrictedRow(Vec<(Column, Value)>);
|
||||
|
|
@ -32,8 +32,7 @@ impl RestrictedRow {
|
|||
self.0.is_empty()
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item=&(Column, Value)> {
|
||||
pub fn iter(&self) -> impl Iterator<Item = &(Column, Value)> {
|
||||
self.0.iter()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::internals::row::Row;
|
||||
use crate::operation::{InsertionValues, ColumnSelection};
|
||||
use crate::operation::{ColumnSelection, InsertionValues};
|
||||
use crate::result::DbResult;
|
||||
use crate::type_system::{DbType, IndexableValue, Uuid, Value};
|
||||
use bimap::BiMap;
|
||||
|
|
@ -20,18 +20,30 @@ pub type TablePosition = usize;
|
|||
pub type ColumnName = String;
|
||||
pub type Column = usize;
|
||||
|
||||
|
||||
impl TableSchema {
|
||||
pub fn new(table_name: TableName, primary_column_name: ColumnName, columns: Vec<ColumnName>, types: Vec<DbType>) -> Self {
|
||||
pub fn new(
|
||||
table_name: TableName,
|
||||
primary_column_name: ColumnName,
|
||||
columns: Vec<ColumnName>,
|
||||
types: Vec<DbType>,
|
||||
) -> Self {
|
||||
let mut column_name_position_mapping: BiMap<ColumnName, Column> = BiMap::new();
|
||||
for (column, column_name) in columns.into_iter().enumerate() {
|
||||
column_name_position_mapping.insert(column_name, column);
|
||||
}
|
||||
let primary_key: Column = match column_name_position_mapping.get_by_left(&primary_column_name).copied() {
|
||||
let primary_key: Column = match column_name_position_mapping
|
||||
.get_by_left(&primary_column_name)
|
||||
.copied()
|
||||
{
|
||||
Some(primary_key) => primary_key,
|
||||
None => unreachable!() // SAFETY: Existence of unique primary key is ensured in validation.
|
||||
None => unreachable!(), // SAFETY: Existence of unique primary key is ensured in validation.
|
||||
};
|
||||
Self { table_name, primary_key, column_name_position_mapping, types }
|
||||
Self {
|
||||
table_name,
|
||||
primary_key,
|
||||
column_name_position_mapping,
|
||||
types,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn table_name(&self) -> &TableName {
|
||||
|
|
@ -43,7 +55,10 @@ impl TableSchema {
|
|||
}
|
||||
|
||||
pub fn get_columns(&self) -> Vec<&ColumnName> {
|
||||
self.column_name_position_mapping.iter().map(|(name, _)| name).collect()
|
||||
self.column_name_position_mapping
|
||||
.iter()
|
||||
.map(|(name, _)| name)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn does_column_exist(&self, column_name: &ColumnName) -> bool {
|
||||
|
|
@ -51,11 +66,17 @@ impl TableSchema {
|
|||
}
|
||||
|
||||
pub fn get_column(&self, column_name: &ColumnName) -> Option<Column> {
|
||||
self.column_name_position_mapping.get_by_left(column_name).copied()
|
||||
self.column_name_position_mapping
|
||||
.get_by_left(column_name)
|
||||
.copied()
|
||||
}
|
||||
|
||||
pub fn all_selection(&self) -> ColumnSelection {
|
||||
let mut selection: ColumnSelection = self.column_name_position_mapping.iter().map(|(_, column)| *column).collect();
|
||||
let mut selection: ColumnSelection = self
|
||||
.column_name_position_mapping
|
||||
.iter()
|
||||
.map(|(_, column)| *column)
|
||||
.collect();
|
||||
selection.sort();
|
||||
selection
|
||||
}
|
||||
|
|
@ -76,13 +97,10 @@ impl TableSchema {
|
|||
|
||||
// Assumes `column` comes from a validated source.
|
||||
pub fn column_name_from_column(&self, column: Column) -> ColumnName {
|
||||
match self
|
||||
.column_name_position_mapping
|
||||
.get_by_right(&column)
|
||||
{
|
||||
match self.column_name_position_mapping.get_by_right(&column) {
|
||||
Some(column_name) => column_name.clone(),
|
||||
None => unreachable!() // SAFETY: The only way this function can get a column is from
|
||||
// validation, which guarantees there is such a colun.
|
||||
None => unreachable!(), // SAFETY: The only way this function can get a column is from
|
||||
// validation, which guarantees there is such a colun.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use crate::error::TypeConversionError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
// ==============Types================
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
|
|
@ -82,7 +82,11 @@ impl Value {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn from_text_bytes(bytes: &[u8], type_oid: i32, type_size: i16) -> Result<Value, TypeConversionError> {
|
||||
pub fn from_text_bytes(
|
||||
bytes: &[u8],
|
||||
type_oid: i32,
|
||||
type_size: i16,
|
||||
) -> Result<Value, TypeConversionError> {
|
||||
match (type_oid, type_size) {
|
||||
(701, 8) => {
|
||||
let s = std::str::from_utf8(bytes)?;
|
||||
|
|
@ -91,7 +95,7 @@ impl Value {
|
|||
}
|
||||
(25, -2) => {
|
||||
let s = std::str::from_utf8(bytes)?;
|
||||
let s = &s[..s.len() - 1]; // remove null terminator
|
||||
let s = &s[..s.len() - 1]; // remove null terminator
|
||||
Ok(Value::Indexable(IndexableValue::String(s.to_string())))
|
||||
}
|
||||
(23, 8) => {
|
||||
|
|
@ -111,8 +115,8 @@ impl Value {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{IndexableValue, Value};
|
||||
use crate::error::TypeConversionError::UnknownType;
|
||||
use super::{Value, IndexableValue};
|
||||
|
||||
#[test]
|
||||
fn test_encode_number() {
|
||||
|
|
@ -204,6 +208,9 @@ mod tests {
|
|||
let bytes = value.as_text_bytes();
|
||||
let from_bytes = Value::from_text_bytes(&bytes, oid, size);
|
||||
|
||||
assert!(matches!(from_bytes, Err(UnknownType { oid: 2950, size: 8 })))
|
||||
assert!(matches!(
|
||||
from_bytes,
|
||||
Err(UnknownType { oid: 2950, size: 8 })
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue