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.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bimap"
|
||||||
|
version = "0.6.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "minisql"
|
name = "minisql"
|
||||||
version = "0.1.0"
|
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
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bimap = "0.6.3"
|
||||||
|
|
|
||||||
123
src/main.rs
123
src/main.rs
|
|
@ -1,4 +1,5 @@
|
||||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||||
|
use bimap::BiMap;
|
||||||
|
|
||||||
// ==============SQL operations================
|
// ==============SQL operations================
|
||||||
// TODO: Note that every operation has a table name.
|
// TODO: Note that every operation has a table name.
|
||||||
|
|
@ -112,7 +113,8 @@ struct ColumnIndex {
|
||||||
struct TableSchema {
|
struct TableSchema {
|
||||||
table_name: TableName, // used for descriptive errors
|
table_name: TableName, // used for descriptive errors
|
||||||
primary_key: ColumnPosition,
|
primary_key: ColumnPosition,
|
||||||
columns: HashMap<ColumnName, (DbType, ColumnPosition)>
|
column_name_position_mapping: BiMap<ColumnName, ColumnPosition>,
|
||||||
|
types: Vec<DbType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
|
@ -219,8 +221,17 @@ impl ColumnIndex {
|
||||||
|
|
||||||
impl TableSchema {
|
impl TableSchema {
|
||||||
fn get_column(&self, column_name: &ColumnName) -> DbResult<(DbType, ColumnPosition)> {
|
fn get_column(&self, column_name: &ColumnName) -> DbResult<(DbType, ColumnPosition)> {
|
||||||
match self.columns.get(column_name) {
|
match self.column_name_position_mapping.get_by_left(column_name) {
|
||||||
Some((type_, column_position)) => Ok((*type_, *column_position)),
|
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()))
|
None => Err(Error::ColumnDoesNotExist(self.table_name.clone(), column_name.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -238,10 +249,17 @@ impl TableSchema {
|
||||||
Ok(positions)
|
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>> {
|
fn column_positions_from_column_selection(&self, column_selection: &ColumnSelection) -> DbResult<Vec<ColumnPosition>> {
|
||||||
match column_selection {
|
match column_selection {
|
||||||
ColumnSelection::All => {
|
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();
|
column_positions.sort();
|
||||||
Ok(column_positions)
|
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 {
|
impl Table {
|
||||||
|
|
@ -324,10 +393,25 @@ impl Table {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert(&mut self, values: InsertionValues) {
|
fn insert(&mut self, values: InsertionValues) -> DbResult<()> {
|
||||||
// 1. You need to update indices
|
let (id, row) = self.schema.row_from_insertion_values(values)?;
|
||||||
// 2. you simply insert the data
|
|
||||||
todo!()
|
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>) {
|
fn delete_where(&mut self, maybe_condition: Option<Condition>) {
|
||||||
|
|
@ -344,6 +428,21 @@ impl ColumnIndex {
|
||||||
None => HashSet::new(),
|
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 {
|
enum Response {
|
||||||
|
|
@ -354,9 +453,15 @@ enum Response {
|
||||||
|
|
||||||
type DbResult<A> = Result<A, Error>;
|
type DbResult<A> = Result<A, Error>;
|
||||||
|
|
||||||
|
// #[derive(Debug)]
|
||||||
enum Error {
|
enum Error {
|
||||||
ColumnDoesNotExist(TableName, ColumnName),
|
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() {
|
fn main() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue