Skip to content

Commit

Permalink
prevent duplicate key entrees
Browse files Browse the repository at this point in the history
  • Loading branch information
GlenDC committed Apr 6, 2024
1 parent 224c805 commit 15eb5e9
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 4 deletions.
6 changes: 6 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,10 @@ pub mod __internal {

pub use bitvec::{bitvec, order::Lsb0, slice::IterOnes, vec::BitVec};
pub use hashbrown::HashMap;

pub mod hash_map {
//! Internal types related to hash map.

pub use hashbrown::hash_map::Entry;
}
}
30 changes: 26 additions & 4 deletions venndb-macros/src/generate_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,15 +199,36 @@ pub fn generate_db_struct_method_append(
) -> TokenStream {
let method_doc = format!("Append a new instance of [`{}`] to the database.", name);

let db_field_inserts: Vec<_> = fields
let db_field_insert_checks: Vec<_> = fields
.iter()
.map(|info| match info {
.filter_map(|info| match info {
FieldInfo::Key(field) => {
let map_name = field.map_name();
let field_name = field.name();
let entry_field_name = format_ident!("entry_{}", field_name);

Some(quote! {
// TODO: handle duplicate key,
// but only have error if we have possible error cases
let #entry_field_name = match self.#map_name.entry(data.#field_name) {
::venndb::__internal::hash_map::Entry::Occupied(_) => todo!("duplicate key: return error"),
::venndb::__internal::hash_map::Entry::Vacant(entry) => entry,
};
})
}
FieldInfo::Filter(_) => None,
})
.collect();

let db_field_insert_commits: Vec<_> = fields
.iter()
.map(|info| match info {
FieldInfo::Key(field) => {
let field_name = field.name();
let entry_field_name = format_ident!("entry_{}", field_name);

quote! {
self.#map_name.insert(data.#field_name.clone(), index);
#entry_field_name.insert(index);
}
}
FieldInfo::Filter(field) => {
Expand All @@ -227,7 +248,8 @@ pub fn generate_db_struct_method_append(
#vis fn append(&mut self, data: #name) {
let index = self.rows.len();

#(#db_field_inserts)*
#(#db_field_insert_checks)*
#(#db_field_insert_commits)*

self.rows.push(data);
}
Expand Down
28 changes: 28 additions & 0 deletions venndb-usage/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,32 @@ mod tests {
let mut query = db.query();
assert!(query.is_active(false).execute().is_none());
}

#[test]
#[should_panic]
fn test_employee_duplicate_key() {
// TODO: replace with error instead of panic
let mut db = EmployeeDB::default();
db.append(Employee {
id: 1,
name: "Alice".to_string(),
is_manager: true,
is_admin: false,
is_active: true,
department: Department::Engineering,
});

// duplicate key: id (=1)
db.append(Employee {
id: 1,
name: "Bob".to_string(),
is_manager: false,
is_admin: false,
is_active: true,
department: Department::Engineering,
});
}

// TODO: add test to ensure that no other keys
// have already been inserted!
}

0 comments on commit 15eb5e9

Please sign in to comment.