First attempt at UPDATE
This commit is contained in:
parent
20615508a2
commit
e0876bb0f1
3 changed files with 124 additions and 9 deletions
9
Cargo.lock
generated
9
Cargo.lock
generated
|
|
@ -2,6 +2,15 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "bimap"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7"
|
||||
|
||||
[[package]]
|
||||
name = "minisql"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bimap",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -6,3 +6,4 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bimap = "0.6.3"
|
||||
|
|
|
|||
123
src/main.rs
123
src/main.rs
|
|
@ -1,4 +1,5 @@
|
|||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use bimap::BiMap;
|
||||
|
||||
// ==============SQL operations================
|
||||
// TODO: Note that every operation has a table name.
|
||||
|
|
@ -112,7 +113,8 @@ struct ColumnIndex {
|
|||
struct TableSchema {
|
||||
table_name: TableName, // used for descriptive errors
|
||||
primary_key: ColumnPosition,
|
||||
columns: HashMap<ColumnName, (DbType, ColumnPosition)>
|
||||
column_name_position_mapping: BiMap<ColumnName, ColumnPosition>,
|
||||
types: Vec<DbType>,
|
||||
}
|
||||
|
||||
// TODO
|
||||
|
|
@ -219,8 +221,17 @@ impl ColumnIndex {
|
|||
|
||||
impl TableSchema {
|
||||
fn get_column(&self, column_name: &ColumnName) -> DbResult<(DbType, ColumnPosition)> {
|
||||
match self.columns.get(column_name) {
|
||||
Some((type_, column_position)) => Ok((*type_, *column_position)),
|
||||
match self.column_name_position_mapping.get_by_left(column_name) {
|
||||
Some(column_position) => {
|
||||
match self.types.get(*column_position) {
|
||||
Some(type_) => {
|
||||
Ok((*type_, *column_position))
|
||||
},
|
||||
None => {
|
||||
Err(Error::MissingTypeAnnotationOfColumn(self.table_name.clone(), *column_position))
|
||||
}
|
||||
}
|
||||
},
|
||||
None => Err(Error::ColumnDoesNotExist(self.table_name.clone(), column_name.clone()))
|
||||
}
|
||||
}
|
||||
|
|
@ -238,10 +249,17 @@ impl TableSchema {
|
|||
Ok(positions)
|
||||
}
|
||||
|
||||
fn column_name_from_column_position(&self, column_position: ColumnPosition) -> DbResult<ColumnName> {
|
||||
match self.column_name_position_mapping.get_by_right(&column_position) {
|
||||
Some(column_name) => Ok(column_name.clone()),
|
||||
None => Err(Error::ColumnPositionDoesNotExist(self.table_name.clone(), column_position))
|
||||
}
|
||||
}
|
||||
|
||||
fn column_positions_from_column_selection(&self, column_selection: &ColumnSelection) -> DbResult<Vec<ColumnPosition>> {
|
||||
match column_selection {
|
||||
ColumnSelection::All => {
|
||||
let mut column_positions: Vec<ColumnPosition> = self.columns.values().map(|(_, column_position)| *column_position).collect();
|
||||
let mut column_positions: Vec<ColumnPosition> = self.column_name_position_mapping.iter().map(|(_, column_position)| *column_position).collect();
|
||||
column_positions.sort();
|
||||
Ok(column_positions)
|
||||
},
|
||||
|
|
@ -252,6 +270,57 @@ impl TableSchema {
|
|||
}
|
||||
}
|
||||
|
||||
fn number_of_columns(&self) -> usize {
|
||||
self.column_name_position_mapping.len()
|
||||
}
|
||||
|
||||
fn row_from_insertion_values(&self, insertion_values: InsertionValues) -> DbResult<(UUID, Row)> {
|
||||
// TODO: There should be proper validation of the insertion_values.
|
||||
// And it shouldn't really be done here.
|
||||
//
|
||||
// In the below we don't check for duplicate column names
|
||||
//
|
||||
let number_of_columns = self.number_of_columns();
|
||||
if number_of_columns != insertion_values.len() {
|
||||
return Err(Error::MismatchBetweenInsertValuesAndColumns(self.table_name.clone(), insertion_values))
|
||||
}
|
||||
|
||||
let mut row: Vec<DbValue> = Vec::with_capacity(number_of_columns);
|
||||
|
||||
let mut values: HashMap<ColumnName, DbValue> = HashMap::new();
|
||||
for (column_name, db_value) in &insertion_values {
|
||||
values.insert(column_name.clone(), db_value.clone());
|
||||
}
|
||||
|
||||
for column_position in 0..number_of_columns {
|
||||
let column_name: ColumnName = self.column_name_from_column_position(column_position)?;
|
||||
match values.get(&column_name) {
|
||||
Some(db_value) => {
|
||||
row.push(db_value.clone())
|
||||
},
|
||||
None => {
|
||||
return Err(Error::MissingColumnInInsertValues(self.table_name.clone(), column_name, insertion_values))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let id = match row.get(self.primary_key) {
|
||||
Some(val) => {
|
||||
match val {
|
||||
DbValue::Indexable(IndexableDbValue::UUID(id)) => {
|
||||
id
|
||||
},
|
||||
_ =>
|
||||
unreachable!()
|
||||
}
|
||||
},
|
||||
None =>
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
Ok((*id, row))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Table {
|
||||
|
|
@ -324,10 +393,25 @@ impl Table {
|
|||
}
|
||||
}
|
||||
|
||||
fn insert(&mut self, values: InsertionValues) {
|
||||
// 1. You need to update indices
|
||||
// 2. you simply insert the data
|
||||
todo!()
|
||||
fn insert(&mut self, values: InsertionValues) -> DbResult<()> {
|
||||
let (id, row) = self.schema.row_from_insertion_values(values)?;
|
||||
|
||||
if self.rows.get(&id).is_some() {
|
||||
return Err(Error::AttemptingToInsertAlreadyPresentId(self.schema.table_name.clone(), id))
|
||||
}
|
||||
|
||||
for (column_position, column_index) in &mut self.indexes {
|
||||
match row.get(*column_position) {
|
||||
Some(DbValue::Indexable(val)) => {
|
||||
column_index.add(val.clone(), id)
|
||||
},
|
||||
Some(_) => {},
|
||||
None => return Err(Error::ColumnPositionDoesNotExist(self.schema.table_name.clone(), *column_position))
|
||||
}
|
||||
}
|
||||
|
||||
let _ = self.rows.insert(id, row);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn delete_where(&mut self, maybe_condition: Option<Condition>) {
|
||||
|
|
@ -344,6 +428,21 @@ impl ColumnIndex {
|
|||
None => HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn add(&mut self, value: IndexableDbValue, id: UUID) {
|
||||
match self.index.get_mut(&value) {
|
||||
Some(ids) => {
|
||||
ids.insert(id);
|
||||
},
|
||||
None => {
|
||||
self.index.insert(value, HashSet::from([id]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn remove(&mut self, id: UUID) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
enum Response {
|
||||
|
|
@ -354,9 +453,15 @@ enum Response {
|
|||
|
||||
type DbResult<A> = Result<A, Error>;
|
||||
|
||||
// #[derive(Debug)]
|
||||
enum Error {
|
||||
ColumnDoesNotExist(TableName, ColumnName),
|
||||
ValueDoesNotMatchExpectedType(TableName, ColumnName, DbType, DbValue)
|
||||
ColumnPositionDoesNotExist(TableName, ColumnPosition),
|
||||
ValueDoesNotMatchExpectedType(TableName, ColumnName, DbType, DbValue),
|
||||
AttemptingToInsertAlreadyPresentId(TableName, UUID),
|
||||
MissingTypeAnnotationOfColumn(TableName, ColumnPosition),
|
||||
MissingColumnInInsertValues(TableName, ColumnName, InsertionValues),
|
||||
MismatchBetweenInsertValuesAndColumns(TableName, InsertionValues),
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue