From dbeda9dc4546f3a35eb543e906afc787fade5b81 Mon Sep 17 00:00:00 2001 From: Michael Vlach Date: Wed, 31 May 2023 21:09:32 +0200 Subject: [PATCH] [db] Remove dictionary #547 (#550) * fix complex data removal * fix coverage --- src/agdb/collections.rs | 1 - src/agdb/collections/dictionary.rs | 714 --------------------- src/agdb/collections/map.rs | 18 +- src/agdb/collections/multi_map.rs | 11 +- src/agdb/collections/vec.rs | 68 +- src/agdb/command.rs | 37 +- src/agdb/db.rs | 297 ++------- src/agdb/db/db_id.rs | 28 +- src/agdb/db/db_key_value.rs | 46 +- src/agdb/db/db_key_value_index.rs | 68 -- src/agdb/db/db_value.rs | 410 ++++-------- src/agdb/graph.rs | 41 -- src/agdb/query/insert_edges_query.rs | 4 +- src/agdb/query/insert_nodes_query.rs | 2 +- src/agdb/query/insert_values_query.rs | 4 +- src/agdb/query/remove_values_query.rs | 2 +- src/agdb/query/select_query.rs | 18 +- src/agdb/test_utilities/collision_value.rs | 2 +- tests/db_test.rs | 22 +- 19 files changed, 318 insertions(+), 1475 deletions(-) delete mode 100644 src/agdb/collections/dictionary.rs delete mode 100644 src/agdb/db/db_key_value_index.rs diff --git a/src/agdb/collections.rs b/src/agdb/collections.rs index 8245690d9..b320278b6 100644 --- a/src/agdb/collections.rs +++ b/src/agdb/collections.rs @@ -1,5 +1,4 @@ pub mod bit_set; -pub mod dictionary; pub mod indexed_map; pub mod map; pub mod multi_map; diff --git a/src/agdb/collections/dictionary.rs b/src/agdb/collections/dictionary.rs deleted file mode 100644 index 5698d90be..000000000 --- a/src/agdb/collections/dictionary.rs +++ /dev/null @@ -1,714 +0,0 @@ -use super::multi_map::MultiMapStorage; -use super::vec::DbVec; -use crate::collections::vec::VecValue; -use crate::db::db_error::DbError; -use crate::storage::file_storage::FileStorage; -use crate::storage::Storage; -use crate::storage::StorageIndex; -use crate::utilities::serialize::Serialize; -use crate::utilities::serialize::SerializeStatic; -use crate::utilities::stable_hash::StableHash; -use std::cell::RefCell; -use std::marker::PhantomData; -use std::rc::Rc; - -pub trait DictionaryData -where - T: Clone + Default + Eq + PartialEq + StableHash + VecValue, -{ - fn capacity(&self) -> u64; - fn commit(&mut self, id: u64) -> Result<(), DbError>; - fn count(&self, index: u64) -> Result; - fn hash(&self, index: u64) -> Result; - fn indexes(&self, hash: u64) -> Result, DbError>; - fn insert(&mut self, hash: u64, index: u64) -> Result<(), DbError>; - fn remove(&mut self, hash: u64, index: u64) -> Result<(), DbError>; - fn set_capacity(&mut self, capacity: u64) -> Result<(), DbError>; - fn set_count(&mut self, index: u64, count: u64) -> Result<(), DbError>; - fn set_hash(&mut self, index: u64, hash: u64) -> Result<(), DbError>; - fn set_value(&mut self, index: u64, value: &T) -> Result<(), DbError>; - fn transaction(&mut self) -> u64; - fn value(&self, index: u64) -> Result; -} - -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] -pub struct DictionaryIndex(pub u64); - -pub struct DictionaryDataStorage -where - T: Clone + Default + Eq + PartialEq + StableHash + VecValue, - Data: Storage, -{ - storage: Rc>, - storage_index: StorageIndex, - index: MultiMapStorage, - counts: DbVec, - hashes: DbVec, - values: DbVec, -} - -struct DictionaryDataStorageIndexes { - index_index: StorageIndex, - counts_index: StorageIndex, - hashes_index: StorageIndex, - values_index: StorageIndex, -} - -impl SerializeStatic for DictionaryDataStorageIndexes { - fn serialized_size_static() -> u64 { - StorageIndex::serialized_size_static() * 4 - } -} - -impl DictionaryDataStorage -where - T: Clone + Default + Eq + PartialEq + StableHash + VecValue, - Data: Storage, -{ - pub fn new(storage: Rc>) -> Result { - let index = MultiMapStorage::::new(storage.clone())?; - let mut counts = DbVec::::new(storage.clone())?; - let mut hashes = DbVec::::new(storage.clone())?; - let mut values = DbVec::::new(storage.clone())?; - - let id = storage.borrow_mut().transaction(); - - counts.push(&0)?; - hashes.push(&0)?; - values.push(&T::default())?; - - let data_index = DictionaryDataStorageIndexes { - index_index: index.storage_index(), - counts_index: counts.storage_index(), - hashes_index: hashes.storage_index(), - values_index: values.storage_index(), - }; - - let storage_index = storage.borrow_mut().insert(&data_index)?; - - storage.borrow_mut().commit(id)?; - - Ok(Self { - storage, - storage_index, - index, - counts, - hashes, - values, - }) - } - - pub fn from_storage( - storage: Rc>, - storage_index: StorageIndex, - ) -> Result { - let data_index = storage - .borrow_mut() - .value::(storage_index)?; - let index = MultiMapStorage::::from_storage( - storage.clone(), - data_index.index_index, - )?; - let counts = DbVec::::from_storage(storage.clone(), data_index.counts_index)?; - let hashes = DbVec::::from_storage(storage.clone(), data_index.hashes_index)?; - let values = DbVec::::from_storage(storage.clone(), data_index.values_index)?; - - Ok(Self { - storage, - storage_index, - index, - counts, - hashes, - values, - }) - } - - pub fn storage_index(&self) -> StorageIndex { - self.storage_index - } -} - -impl DictionaryData for DictionaryDataStorage -where - T: Clone + Default + Eq + PartialEq + StableHash + VecValue, - Data: Storage, -{ - fn capacity(&self) -> u64 { - self.counts.len() - } - - fn commit(&mut self, id: u64) -> Result<(), DbError> { - self.storage.borrow_mut().commit(id) - } - - fn count(&self, index: u64) -> Result { - self.counts.value(index) - } - - fn indexes(&self, hash: u64) -> Result, DbError> { - self.index.values(&hash) - } - - fn insert(&mut self, hash: u64, index: u64) -> Result<(), DbError> { - self.index.insert(&hash, &index) - } - - fn hash(&self, index: u64) -> Result { - self.hashes.value(index) - } - - fn remove(&mut self, hash: u64, index: u64) -> Result<(), DbError> { - self.index.remove_value(&hash, &index) - } - - fn set_capacity(&mut self, capacity: u64) -> Result<(), DbError> { - self.counts.resize(capacity, &0)?; - self.hashes.resize(capacity, &0)?; - self.values.resize(capacity, &T::default()) - } - - fn set_count(&mut self, index: u64, count: u64) -> Result<(), DbError> { - self.counts.replace(index, &count)?; - Ok(()) - } - - fn set_hash(&mut self, index: u64, hash: u64) -> Result<(), DbError> { - self.hashes.replace(index, &hash)?; - Ok(()) - } - - fn set_value(&mut self, index: u64, value: &T) -> Result<(), DbError> { - self.values.replace(index, value)?; - Ok(()) - } - - fn transaction(&mut self) -> u64 { - self.storage.borrow_mut().transaction() - } - - fn value(&self, index: u64) -> Result { - self.values.value(index) - } -} - -impl Serialize for DictionaryDataStorageIndexes { - fn serialize(&self) -> Vec { - let mut bytes = Vec::::new(); - bytes.reserve(self.serialized_size() as usize); - bytes.extend(self.index_index.serialize()); - bytes.extend(self.counts_index.serialize()); - bytes.extend(self.hashes_index.serialize()); - bytes.extend(self.values_index.serialize()); - - bytes - } - - fn deserialize(bytes: &[u8]) -> Result { - if bytes.len() < Self::serialized_size_static() as usize { - return Err(DbError::from( - "DictionaryDataStorageIndexes deserialization error: not enough data", - )); - } - - Ok(DictionaryDataStorageIndexes { - index_index: StorageIndex::deserialize(bytes)?, - counts_index: StorageIndex::deserialize( - &bytes[StorageIndex::serialized_size_static() as usize..], - )?, - hashes_index: StorageIndex::deserialize( - &bytes[(StorageIndex::serialized_size_static() * 2) as usize..], - )?, - values_index: StorageIndex::deserialize( - &bytes[(StorageIndex::serialized_size_static() * 3) as usize..], - )?, - }) - } - - fn serialized_size(&self) -> u64 { - Self::serialized_size_static() - } -} - -pub struct DictionaryImpl -where - T: Clone + Default + Eq + PartialEq + StableHash + VecValue, - Data: DictionaryData, -{ - pub data: Data, - pub phantom_data: PhantomData, -} - -impl DictionaryImpl -where - T: Clone + Default + Eq + PartialEq + StableHash + VecValue, - Data: DictionaryData, -{ - #[allow(dead_code)] - pub fn count(&self, index: DictionaryIndex) -> Result, DbError> { - if self.is_valid_index(index.0) { - let count = self.data.count(index.0)?; - - if count != 0 { - return Ok(Some(count)); - } - } - - Ok(None) - } - - pub fn len(&self) -> Result { - self.data.count(0) - } - - #[allow(dead_code)] - pub fn index(&self, value: &T) -> Result, DbError> { - self.find_value(value.stable_hash(), value) - } - - pub fn insert(&mut self, value: &T) -> Result { - let hash = value.stable_hash(); - let index; - - let id = self.data.transaction(); - - if let Some(i) = self.find_value(hash, value)? { - index = i; - let count = self.data.count(index.0)?; - self.data.set_count(index.0, count + 1)?; - } else { - index = DictionaryIndex(self.insert_new(hash, value)?); - } - - self.data.commit(id)?; - - Ok(index) - } - - pub fn remove(&mut self, index: DictionaryIndex) -> Result { - if self.is_valid_index(index.0) { - let count = self.data.count(index.0)?; - - if count != 0 { - let id = self.data.transaction(); - - if count == 1 { - self.remove_value(index.0)? - } else { - self.data.set_count(index.0, count - 1)? - } - - self.data.commit(id)?; - return Ok(true); - } - } - - Ok(false) - } - - pub fn value(&self, index: DictionaryIndex) -> Result, DbError> { - let mut v = None; - - if self.is_valid_index(index.0) && self.data.count(index.0)? != 0 { - v = Some(self.data.value(index.0)?); - } - - Ok(v) - } - - fn find_value(&self, hash: u64, value: &T) -> Result, DbError> { - for index in self.data.indexes(hash)? { - if *value == self.data.value(index)? { - return Ok(Some(DictionaryIndex(index))); - } - } - - Ok(None) - } - - fn free_index(&mut self, index: u64) -> Result<(), DbError> { - let next_free_index = self.data.hash(0)?; - self.data.set_hash(index, next_free_index)?; - self.data.set_hash(0, index) - } - - fn get_free_index(&mut self) -> Result { - let mut free_index = self.data.hash(0)?; - - if free_index == 0 { - free_index = self.data.capacity(); - self.data.set_capacity(free_index + 1)?; - } else { - let next_free_index = self.data.hash(free_index)?; - self.data.set_hash(0, next_free_index)?; - } - - Ok(free_index) - } - - fn insert_new(&mut self, hash: u64, value: &T) -> Result { - let index = self.get_free_index()?; - - self.data.insert(hash, index)?; - self.data.set_hash(index, hash)?; - self.data.set_count(index, 1)?; - self.data.set_value(index, value)?; - - let len = self.len()?; - self.data.set_count(0, len + 1)?; - - Ok(index) - } - - fn is_valid_index(&self, index: u64) -> bool { - index != 0 && index < self.data.capacity() - } - - fn remove_value(&mut self, index: u64) -> Result<(), DbError> { - let hash = self.data.hash(index)?; - self.data.remove(hash, index)?; - self.free_index(index)?; - self.data.set_count(index, 0)?; - let len = self.len()?; - self.data.set_count(0, len - 1) - } -} - -pub type DictionaryStorage = - DictionaryImpl>; - -impl DictionaryStorage -where - T: Clone + Default + Eq + PartialEq + StableHash + VecValue, - Data: Storage, -{ - pub fn new(storage: Rc>) -> Result { - Ok(Self { - data: DictionaryDataStorage::new(storage)?, - phantom_data: PhantomData, - }) - } - - pub fn from_storage(storage: Rc>, index: StorageIndex) -> Result { - Ok(Self { - data: DictionaryDataStorage::from_storage(storage, index)?, - phantom_data: PhantomData, - }) - } - - pub fn storage_index(&self) -> StorageIndex { - self.data.storage_index() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::test_utilities::collision_value::CollisionValue; - use crate::test_utilities::test_file::TestFile; - use std::cmp::Ordering; - - #[test] - fn count_invalid_index() { - let test_file = TestFile::new(); - let storage = Rc::new(RefCell::new( - FileStorage::new(test_file.file_name()).unwrap(), - )); - let dictionary = DictionaryStorage::::new(storage).unwrap(); - - assert_eq!(dictionary.count(DictionaryIndex(u64::MAX)), Ok(None)); - } - - #[test] - fn index() { - let test_file = TestFile::new(); - let storage = Rc::new(RefCell::new( - FileStorage::new(test_file.file_name()).unwrap(), - )); - let mut dictionary = DictionaryStorage::::new(storage).unwrap(); - - let index = dictionary.insert(&10).unwrap(); - - assert_eq!(dictionary.index(&10), Ok(Some(index))); - } - - #[test] - fn index_missing_value() { - let test_file = TestFile::new(); - let storage = Rc::new(RefCell::new( - FileStorage::new(test_file.file_name()).unwrap(), - )); - let dictionary = DictionaryStorage::::new(storage).unwrap(); - - assert_eq!(dictionary.index(&10), Ok(None)); - } - - #[test] - fn index_removed_value() { - let test_file = TestFile::new(); - let storage = Rc::new(RefCell::new( - FileStorage::new(test_file.file_name()).unwrap(), - )); - let mut dictionary = DictionaryStorage::::new(storage).unwrap(); - - let index = dictionary.insert(&10).unwrap(); - dictionary.remove(index).unwrap(); - - assert_eq!(dictionary.index(&10), Ok(None)); - } - - #[test] - fn index_reuse() { - let test_file = TestFile::new(); - let storage = Rc::new(RefCell::new( - FileStorage::new(test_file.file_name()).unwrap(), - )); - let mut dictionary = DictionaryStorage::::new(storage).unwrap(); - - let index1 = dictionary.insert(&5).unwrap(); - let index2 = dictionary.insert(&10).unwrap(); - let index3 = dictionary.insert(&7).unwrap(); - - dictionary.remove(index2).unwrap(); - dictionary.remove(index1).unwrap(); - dictionary.remove(index3).unwrap(); - - assert_eq!(dictionary.count(index1), Ok(None)); - assert_eq!(dictionary.count(index2), Ok(None)); - assert_eq!(dictionary.count(index3), Ok(None)); - - assert_eq!(dictionary.insert(&3), Ok(index3)); - assert_eq!(dictionary.insert(&2), Ok(index1)); - assert_eq!(dictionary.insert(&1), Ok(index2)); - - assert_eq!(dictionary.value(index1), Ok(Some(2))); - assert_eq!(dictionary.value(index2), Ok(Some(1))); - assert_eq!(dictionary.value(index3), Ok(Some(3))); - } - - #[test] - fn index_with_collisions() { - let test_file = TestFile::new(); - let storage = Rc::new(RefCell::new( - FileStorage::new(test_file.file_name()).unwrap(), - )); - let mut dictionary = DictionaryStorage::>::new(storage).unwrap(); - - let index1 = dictionary.insert(&CollisionValue::new(1)).unwrap(); - let index2 = dictionary.insert(&CollisionValue::new(2)).unwrap(); - let index3 = dictionary.insert(&CollisionValue::new(3)).unwrap(); - - assert_eq!(dictionary.index(&CollisionValue::new(1)), Ok(Some(index1))); - assert_eq!(dictionary.index(&CollisionValue::new(2)), Ok(Some(index2))); - assert_eq!(dictionary.index(&CollisionValue::new(3)), Ok(Some(index3))); - } - - #[test] - fn insert() { - let test_file = TestFile::new(); - let storage = Rc::new(RefCell::new( - FileStorage::new(test_file.file_name()).unwrap(), - )); - let mut dictionary = DictionaryStorage::::new(storage).unwrap(); - - let index = dictionary.insert(&10).unwrap(); - - assert_eq!(dictionary.len(), Ok(1)); - assert_eq!(dictionary.value(index), Ok(Some(10_i64))); - assert_eq!(dictionary.count(index), Ok(Some(1))); - } - - #[test] - fn insert_multiple() { - let test_file = TestFile::new(); - let storage = Rc::new(RefCell::new( - FileStorage::new(test_file.file_name()).unwrap(), - )); - let mut dictionary = DictionaryStorage::::new(storage).unwrap(); - - let index1 = dictionary.insert(&10).unwrap(); - let index2 = dictionary.insert(&15).unwrap(); - let index3 = dictionary.insert(&20).unwrap(); - - assert_eq!(dictionary.len(), Ok(3)); - - assert_eq!(dictionary.value(index1).unwrap(), Some(10_i64)); - assert_eq!(dictionary.count(index1), Ok(Some(1))); - - assert_eq!(dictionary.value(index2).unwrap(), Some(15_i64)); - assert_eq!(dictionary.count(index2), Ok(Some(1))); - - assert_eq!(dictionary.value(index3).unwrap(), Some(20_i64)); - assert_eq!(dictionary.count(index3), Ok(Some(1))); - } - - #[test] - fn insert_same() { - let test_file = TestFile::new(); - let storage = Rc::new(RefCell::new( - FileStorage::new(test_file.file_name()).unwrap(), - )); - let mut dictionary = DictionaryStorage::::new(storage).unwrap(); - - dictionary.insert(&10).unwrap(); - - let index2 = dictionary.insert(&15).unwrap(); - - assert_eq!(dictionary.insert(&15).unwrap(), index2); - assert_eq!(dictionary.insert(&15).unwrap(), index2); - - dictionary.insert(&20).unwrap(); - - assert_eq!(dictionary.len(), Ok(3)); - assert_eq!(dictionary.count(index2), Ok(Some(3))); - } - - #[test] - fn remove() { - let test_file = TestFile::new(); - let storage = Rc::new(RefCell::new( - FileStorage::new(test_file.file_name()).unwrap(), - )); - let mut dictionary = DictionaryStorage::::new(storage).unwrap(); - - let index = dictionary.insert(&10).unwrap(); - dictionary.remove(index).unwrap(); - - assert_eq!(dictionary.value(index), Ok(None)); - assert_eq!(dictionary.count(index), Ok(None)); - - dictionary.remove(index).unwrap(); - - assert_eq!(dictionary.value(index), Ok(None)); - assert_eq!(dictionary.count(index), Ok(None)); - } - - #[test] - fn remove_duplicated() { - let test_file = TestFile::new(); - let storage = Rc::new(RefCell::new( - FileStorage::new(test_file.file_name()).unwrap(), - )); - let mut dictionary = DictionaryStorage::::new(storage).unwrap(); - - let index = dictionary.insert(&10).unwrap(); - dictionary.insert(&10).unwrap(); - dictionary.insert(&10).unwrap(); - - assert_eq!(dictionary.value(index), Ok(Some(10))); - assert_eq!(dictionary.count(index), Ok(Some(3))); - - dictionary.remove(index).unwrap(); - - assert_eq!(dictionary.value(index), Ok(Some(10))); - assert_eq!(dictionary.count(index), Ok(Some(2))); - - dictionary.remove(index).unwrap(); - dictionary.remove(index).unwrap(); - - assert_eq!(dictionary.value(index), Ok(None)); - assert_eq!(dictionary.count(index), Ok(None)); - } - - #[test] - fn remove_missing() { - let test_file = TestFile::new(); - let storage = Rc::new(RefCell::new( - FileStorage::new(test_file.file_name()).unwrap(), - )); - let mut dictionary = DictionaryStorage::::new(storage).unwrap(); - - let index = dictionary.insert(&10).unwrap(); - - assert_eq!(dictionary.len(), Ok(1)); - - dictionary.remove(DictionaryIndex(index.0 + 1)).unwrap(); - - assert_eq!(dictionary.len(), Ok(1)); - } - - #[test] - fn restore_from_file() { - let test_file = TestFile::new(); - let storage = Rc::new(RefCell::new( - FileStorage::new(test_file.file_name()).unwrap(), - )); - - let storage_index; - let index1; - let index2; - let index3; - let index4; - - { - let mut dictionary = DictionaryStorage::::new(storage.clone()).unwrap(); - storage_index = dictionary.storage_index(); - - index1 = dictionary.insert(&10).unwrap(); - dictionary.insert(&10).unwrap(); - index2 = dictionary.insert(&15).unwrap(); - index3 = dictionary.insert(&7).unwrap(); - index4 = dictionary.insert(&20).unwrap(); - dictionary.remove(index2).unwrap(); - } - - let dictionary = DictionaryStorage::::from_storage(storage, storage_index).unwrap(); - - assert_eq!(dictionary.len(), Ok(3)); - assert_eq!(dictionary.count(index1), Ok(Some(2))); - assert_eq!(dictionary.value(index1), Ok(Some(10))); - assert_eq!(dictionary.value(index2), Ok(None)); - assert_eq!(dictionary.value(index3), Ok(Some(7))); - assert_eq!(dictionary.value(index4), Ok(Some(20))); - } - - #[test] - fn value_missing_index() { - let test_file = TestFile::new(); - let storage = Rc::new(RefCell::new( - FileStorage::new(test_file.file_name()).unwrap(), - )); - let dictionary = DictionaryStorage::::new(storage).unwrap(); - assert_eq!(dictionary.value(DictionaryIndex(1)), Ok(None)); - } - - #[test] - fn bad_deserialize() { - assert_eq!( - DictionaryDataStorageIndexes::deserialize(&Vec::::new()) - .err() - .unwrap(), - DbError::from("DictionaryDataStorageIndexes deserialization error: not enough data") - ); - } - - #[test] - #[allow(clippy::clone_on_copy)] - fn derived_from_clone() { - let _ = DictionaryIndex(0).clone(); - } - - #[test] - fn derived_from_debug() { - let _ = format!("{:?}", DictionaryIndex(0)); - } - - #[test] - fn derived_from_default() { - let _ = DictionaryIndex::default(); - } - - #[test] - fn derived_from_ord() { - assert_eq!(DictionaryIndex(1).cmp(&DictionaryIndex(1)), Ordering::Equal); - } - - #[test] - fn derived_from_partial_ord() { - let mut ids = vec![DictionaryIndex(3), DictionaryIndex(0), DictionaryIndex(1)]; - ids.sort(); - assert_eq!( - ids, - vec![DictionaryIndex(0), DictionaryIndex(1), DictionaryIndex(3)] - ); - } -} diff --git a/src/agdb/collections/map.rs b/src/agdb/collections/map.rs index 46a44a7cf..01b0112e4 100644 --- a/src/agdb/collections/map.rs +++ b/src/agdb/collections/map.rs @@ -54,16 +54,24 @@ impl SerializeStatic for MapValueState { } impl VecValue for MapValueState { + fn store(&self, _storage: &mut S) -> Result, DbError> { + Ok(self.serialize()) + } + + fn load(_storage: &S, bytes: &[u8]) -> Result { + Self::deserialize(bytes) + } + + fn remove(_storage: &mut S, _bytes: &[u8]) -> Result<(), DbError> { + Ok(()) + } + fn storage_len() -> u64 { Self::serialized_size_static() } } -pub trait MapData -where - K: Default + Eq + Hash + PartialEq + StableHash, - T: Default + Eq + PartialEq, -{ +pub trait MapData { fn capacity(&self) -> u64; fn commit(&mut self, id: u64) -> Result<(), DbError>; fn len(&self) -> u64; diff --git a/src/agdb/collections/multi_map.rs b/src/agdb/collections/multi_map.rs index a016308b3..f76326113 100644 --- a/src/agdb/collections/multi_map.rs +++ b/src/agdb/collections/multi_map.rs @@ -112,7 +112,7 @@ where match self.data.state(pos)? { MapValueState::Empty => break, MapValueState::Valid if self.data.key(pos)? == *key => { - self.data.set_state(pos, MapValueState::Deleted)?; + self.drop_value(pos)?; len -= 1; } MapValueState::Valid | MapValueState::Deleted => {} @@ -149,7 +149,6 @@ where if self.data.key(pos)? == *key && self.data.value(pos)? == *value => { self.remove_index(pos)?; - break; } MapValueState::Valid | MapValueState::Deleted => pos = self.next_pos(pos), @@ -238,6 +237,12 @@ where Ok(values) } + fn drop_value(&mut self, pos: u64) -> Result<(), DbError> { + self.data.set_state(pos, MapValueState::Deleted)?; + self.data.set_key(pos, &K::default())?; + self.data.set_value(pos, &T::default()) + } + fn free_index(&mut self, key: &K) -> Result { if self.len() >= self.max_len() { self.rehash(self.capacity() * 2)?; @@ -359,7 +364,7 @@ where } fn remove_index(&mut self, index: u64) -> Result<(), DbError> { - self.data.set_state(index, MapValueState::Deleted)?; + self.drop_value(index)?; self.data.set_len(self.len() - 1)?; if self.len() <= self.min_len() { diff --git a/src/agdb/collections/vec.rs b/src/agdb/collections/vec.rs index 4ba42c822..e1c4e735d 100644 --- a/src/agdb/collections/vec.rs +++ b/src/agdb/collections/vec.rs @@ -19,7 +19,14 @@ pub trait VecData { fn value(&self, index: u64) -> Result; } -pub trait VecValue: Serialize { +pub trait VecValue: Sized { + fn store(&self, storage: &mut S) -> Result, DbError>; + fn load(storage: &S, bytes: &[u8]) -> Result; + fn remove(storage: &mut S, _bytes: &[u8]) -> Result<(), DbError>; + fn storage_len() -> u64; +} + +impl VecValue for u64 { fn store(&self, _storage: &mut S) -> Result, DbError> { Ok(self.serialize()) } @@ -32,16 +39,24 @@ pub trait VecValue: Serialize { Ok(()) } - fn storage_len() -> u64; -} - -impl VecValue for u64 { fn storage_len() -> u64 { Self::serialized_size_static() } } impl VecValue for i64 { + fn store(&self, _storage: &mut S) -> Result, DbError> { + Ok(self.serialize()) + } + + fn load(_storage: &S, bytes: &[u8]) -> Result { + Self::deserialize(bytes) + } + + fn remove(_storage: &mut S, _bytes: &[u8]) -> Result<(), DbError> { + Ok(()) + } + fn storage_len() -> u64 { Self::serialized_size_static() } @@ -90,13 +105,6 @@ where fn offset(index: u64) -> u64 { u64::serialized_size_static() + T::storage_len() * index } - - fn store_value(&mut self, index: u64, value: &T) -> Result<(), E> { - let storage = &mut *self.storage.borrow_mut(); - let bytes = value.store(storage)?; - storage.insert_bytes_at(self.storage_index, Self::offset(index), &bytes)?; - Ok(()) - } } impl VecData for DbVecData @@ -122,6 +130,7 @@ where )?; let current_capacity = self.data.capacity(); + if capacity < current_capacity as u64 { self.data.shrink_to(capacity as usize); } else { @@ -141,8 +150,8 @@ where Self::offset(index), T::storage_len(), )?; - T::remove(storage, &bytes)?; let id = storage.transaction(); + T::remove(storage, &bytes)?; storage.move_at(self.storage_index, offset_from, offset_to, move_len)?; storage.insert_at(self.storage_index, 0, &(self.len() - 1))?; storage.commit(id)?; @@ -150,20 +159,43 @@ where } fn replace(&mut self, index: u64, value: &T) -> Result { - self.store_value(index, value)?; + let storage = &mut *self.storage.borrow_mut(); + let old_bytes = storage.value_as_bytes_at_size( + self.storage_index, + Self::offset(index), + T::storage_len(), + )?; + let id = storage.transaction(); + T::remove(storage, &old_bytes)?; + let bytes = value.store(storage)?; + storage.insert_bytes_at(self.storage_index, Self::offset(index), &bytes)?; + storage.commit(id)?; let old_value = self.data[index as usize].clone(); self.data[index as usize] = value.clone(); + Ok(old_value) } fn resize(&mut self, new_len: u64, value: &T) -> Result<(), E> { + let storage = &mut *self.storage.borrow_mut(); + let id = storage.transaction(); + for index in self.len()..new_len { - self.store_value(index, value)?; + let bytes = value.store(storage)?; + storage.insert_bytes_at(self.storage_index, Self::offset(index), &bytes)?; } - self.storage - .borrow_mut() - .insert_at(self.storage_index, 0, &new_len)?; + for index in new_len..self.len() { + let old_bytes = storage.value_as_bytes_at_size( + self.storage_index, + Self::offset(index), + T::storage_len(), + )?; + T::remove(storage, &old_bytes)?; + } + + storage.insert_at(self.storage_index, 0, &new_len)?; + storage.commit(id)?; self.data.resize_with(new_len as usize, || value.clone()); Ok(()) } diff --git a/src/agdb/command.rs b/src/agdb/command.rs index c75cd31b6..e2dd185cf 100644 --- a/src/agdb/command.rs +++ b/src/agdb/command.rs @@ -1,37 +1,14 @@ -use crate::collections::dictionary::DictionaryIndex; -use crate::db::db_key_value_index::DbKeyValueIndex; use crate::graph::GraphIndex; use crate::DbId; use crate::DbKeyValue; pub(crate) enum Command { - InsertAlias { - alias: String, - id: DbId, - }, - InsertEdge { - from: GraphIndex, - to: GraphIndex, - }, + InsertAlias { alias: String, id: DbId }, + InsertEdge { from: GraphIndex, to: GraphIndex }, InsertNode, - InsertKeyValue { - id: DbId, - key_value: DbKeyValue, - }, - RemoveAlias { - alias: String, - }, - RemoveEdge { - index: GraphIndex, - }, - RemoveKeyValue { - id: DbId, - key_value: DbKeyValueIndex, - }, - RemoveNode { - index: GraphIndex, - }, - RemoveValue { - index: DictionaryIndex, - }, + InsertKeyValue { id: DbId, key_value: DbKeyValue }, + RemoveAlias { alias: String }, + RemoveEdge { index: GraphIndex }, + RemoveKeyValue { id: DbId, key_value: DbKeyValue }, + RemoveNode { index: GraphIndex }, } diff --git a/src/agdb/db.rs b/src/agdb/db.rs index 9e385c7cb..a46c9a40a 100644 --- a/src/agdb/db.rs +++ b/src/agdb/db.rs @@ -5,22 +5,11 @@ pub mod db_key; pub mod db_key_value; pub mod db_value; -pub(crate) mod db_key_value_index; pub(crate) mod db_value_index; mod db_float; use self::db_error::DbError; -use self::db_float::DbFloat; -use self::db_key_value_index::DbKeyValueIndex; -use self::db_value::BYTES_META_VALUE; -use self::db_value::FLOAT_META_VALUE; -use self::db_value::INT_META_VALUE; -use self::db_value::STRING_META_VALUE; -use self::db_value::UINT_META_VALUE; -use self::db_value_index::DbValueIndex; -use crate::collections::dictionary::DictionaryIndex; -use crate::collections::dictionary::DictionaryStorage; use crate::collections::indexed_map::DbIndexedMap; use crate::collections::multi_map::MultiMapStorage; use crate::command::Command; @@ -38,7 +27,6 @@ use crate::utilities::serialize::SerializeStatic; use crate::DbId; use crate::DbKey; use crate::DbKeyValue; -use crate::DbValue; use crate::QueryError; use crate::QueryResult; use crate::Transaction; @@ -49,7 +37,6 @@ use std::rc::Rc; struct DbStorageIndex { graph: StorageIndex, aliases: (StorageIndex, StorageIndex), - dictionary: StorageIndex, values: StorageIndex, } @@ -59,7 +46,6 @@ impl Serialize for DbStorageIndex { self.graph.serialize(), self.aliases.0.serialize(), self.aliases.1.serialize(), - self.dictionary.serialize(), self.values.serialize(), ] .concat() @@ -71,32 +57,25 @@ impl Serialize for DbStorageIndex { let graph = StorageIndex::deserialize(bytes)?; let aliases_1 = StorageIndex::deserialize(&bytes[size..])?; let aliases_2 = StorageIndex::deserialize(&bytes[size * 2..])?; - let dictionary = StorageIndex::deserialize(&bytes[size * 3..])?; - let values = StorageIndex::deserialize(&bytes[size * 4..])?; + let values = StorageIndex::deserialize(&bytes[size * 3..])?; Ok(Self { graph, aliases: (aliases_1, aliases_2), - dictionary, values, }) } fn serialized_size(&self) -> u64 { - i64::serialized_size_static() * 5 + i64::serialized_size_static() * 4 } } -struct DbStorage { +pub struct Db { _storage: Rc>, graph: DbGraph, aliases: DbIndexedMap, - dictionary: DictionaryStorage, - values: MultiMapStorage, -} - -pub struct Db { - storage: DbStorage, + values: MultiMapStorage, undo_stack: Vec, } @@ -159,37 +138,18 @@ impl Db { for command in undo_stack.iter().rev() { match command { - Command::InsertAlias { id, alias } => { - self.storage.aliases.insert(alias, id)?; - } + Command::InsertAlias { id, alias } => self.aliases.insert(alias, id)?, Command::InsertEdge { from, to } => { - self.storage.graph.insert_edge(*from, *to)?; - } - Command::InsertKeyValue { id, key_value } => { - let key = self.insert_value(&key_value.key)?; - let value = self.insert_value(&key_value.value)?; - self.storage - .values - .insert(id, &DbKeyValueIndex { key, value })?; - } - Command::InsertNode => { - self.storage.graph.insert_node()?; - } - Command::RemoveAlias { alias } => { - self.storage.aliases.remove_key(alias)?; - } - Command::RemoveEdge { index } => { - self.storage.graph.remove_edge(*index)?; + self.graph.insert_edge(*from, *to).map(|_| ())? } + Command::InsertKeyValue { id, key_value } => self.values.insert(id, key_value)?, + Command::InsertNode => self.graph.insert_node().map(|_| ())?, + Command::RemoveAlias { alias } => self.aliases.remove_key(alias)?, + Command::RemoveEdge { index } => self.graph.remove_edge(*index)?, Command::RemoveKeyValue { id, key_value } => { - self.storage.values.remove_value(id, key_value)?; - } - Command::RemoveNode { index } => { - self.storage.graph.remove_node(*index)?; - } - Command::RemoveValue { index } => { - self.storage.dictionary.remove(*index)?; + self.values.remove_value(id, key_value)? } + Command::RemoveNode { index } => self.graph.remove_node(*index)?, } } @@ -200,7 +160,6 @@ impl Db { match query_id { QueryId::Id(id) => Ok(DbId(self.graph_index(id.0)?.0)), QueryId::Alias(alias) => Ok(self - .storage .aliases .value(alias)? .ok_or(QueryError::from(format!("Alias '{alias}' not found")))?), @@ -208,19 +167,19 @@ impl Db { } pub(crate) fn insert_alias(&mut self, db_id: DbId, alias: &String) -> Result<(), DbError> { - if let Some(old_alias) = self.storage.aliases.key(&db_id)? { + if let Some(old_alias) = self.aliases.key(&db_id)? { self.undo_stack.push(Command::InsertAlias { id: db_id, alias: old_alias.clone(), }); - self.storage.aliases.remove_key(&old_alias)?; - self.storage.aliases.remove_key(&old_alias)?; + self.aliases.remove_key(&old_alias)?; + self.aliases.remove_key(&old_alias)?; } self.undo_stack.push(Command::RemoveAlias { alias: alias.clone(), }); - self.storage.aliases.insert(alias, &db_id) + self.aliases.insert(alias, &db_id) } pub(crate) fn insert_edge(&mut self, from: &QueryId, to: &QueryId) -> Result { @@ -228,7 +187,6 @@ impl Db { let to = self.db_id(to)?; let index = self - .storage .graph .insert_edge(GraphIndex(from.0), GraphIndex(to.0))?; self.undo_stack.push(Command::RemoveEdge { index }); @@ -241,7 +199,7 @@ impl Db { db_id: DbId, alias: &String, ) -> Result<(), QueryError> { - if let Some(id) = self.storage.aliases.value(alias)? { + if let Some(id) = self.aliases.value(alias)? { return Err(QueryError::from(format!( "Alias '{alias}' already exists ({})", id.0 @@ -251,13 +209,13 @@ impl Db { self.undo_stack.push(Command::RemoveAlias { alias: alias.clone(), }); - self.storage.aliases.insert(alias, &db_id)?; + self.aliases.insert(alias, &db_id)?; Ok(()) } pub(crate) fn insert_node(&mut self) -> Result { - let index = self.storage.graph.insert_node()?; + let index = self.graph.insert_node()?; self.undo_stack.push(Command::RemoveNode { index }); Ok(DbId(index.0)) @@ -266,33 +224,13 @@ impl Db { pub(crate) fn insert_key_value( &mut self, db_id: DbId, - key: &DbKey, - value: &DbValue, + key_value: &DbKeyValue, ) -> Result<(), QueryError> { - let key = self.insert_value(key)?; - - if !key.is_value() { - self.undo_stack.push(Command::RemoveValue { - index: DictionaryIndex(key.index()), - }); - } - - let value = self.insert_value(value)?; - - if !key.is_value() { - self.undo_stack.push(Command::RemoveValue { - index: DictionaryIndex(value.index()), - }); - } - - let key_value = DbKeyValueIndex { key, value }; - self.undo_stack.push(Command::RemoveKeyValue { id: db_id, - key_value, + key_value: key_value.clone(), }); - self.storage.values.insert(&db_id, &key_value)?; - + self.values.insert(&db_id, key_value)?; Ok(()) } @@ -301,7 +239,7 @@ impl Db { QueryId::Id(db_id) => { if let Ok(graph_index) = self.graph_index(db_id.0) { if graph_index.is_node() { - self.remove_node(*db_id, graph_index, self.storage.aliases.key(db_id)?)?; + self.remove_node(*db_id, graph_index, self.aliases.key(db_id)?)?; } else { self.remove_edge(graph_index)?; } @@ -310,7 +248,7 @@ impl Db { } } QueryId::Alias(alias) => { - if let Some(db_id) = self.storage.aliases.value(alias)? { + if let Some(db_id) = self.aliases.value(alias)? { self.remove_node(db_id, GraphIndex(db_id.0), Some(alias.clone()))?; self.remove_all_values(db_id)?; return Ok(true); @@ -322,13 +260,13 @@ impl Db { } pub(crate) fn remove_alias(&mut self, alias: &String) -> Result { - if let Some(id) = self.storage.aliases.value(alias)? { + if let Some(id) = self.aliases.value(alias)? { self.undo_stack.push(Command::InsertAlias { id, alias: alias.clone(), }); - self.storage.aliases.remove_key(alias)?; - self.storage.aliases.remove_key(alias)?; + self.aliases.remove_key(alias)?; + self.aliases.remove_key(alias)?; return Ok(true); } @@ -336,62 +274,20 @@ impl Db { Ok(false) } - pub(crate) fn value(&self, index: &DbValueIndex) -> Result { - if index.is_value() { - match index.get_type() { - BYTES_META_VALUE => { - return Ok(DbValue::Bytes(index.value().to_vec())); - } - INT_META_VALUE => { - let mut bytes = [0_u8; 8]; - bytes.copy_from_slice(index.value()); - return Ok(DbValue::Int(i64::from_le_bytes(bytes))); - } - UINT_META_VALUE => { - let mut bytes = [0_u8; 8]; - bytes.copy_from_slice(index.value()); - return Ok(DbValue::Uint(u64::from_le_bytes(bytes))); - } - FLOAT_META_VALUE => { - let mut bytes = [0_u8; 8]; - bytes.copy_from_slice(index.value()); - return Ok(DbValue::Float(DbFloat::from(f64::from_le_bytes(bytes)))); - } - STRING_META_VALUE => { - return Ok(DbValue::String( - String::from_utf8_lossy(index.value()).to_string(), - )) - } - _ => panic!(), - } - } - - let dictionary_index = DictionaryIndex(index.index()); - let value = self - .storage - .dictionary - .value(dictionary_index)? - .ok_or(QueryError::from(format!( - "Value not found (index: '{}')", - dictionary_index.0 - )))?; - Ok(value) - } - - pub(crate) fn values(&self, db_id: DbId) -> Result, DbError> { - self.storage.values.values(&db_id) + pub(crate) fn values(&self, db_id: DbId) -> Result, DbError> { + self.values.values(&db_id) } fn graph_index(&self, id: i64) -> Result { match id.cmp(&0) { std::cmp::Ordering::Less => { - if self.storage.graph.edge(GraphIndex(id)).is_some() { + if self.graph.edge(GraphIndex(id)).is_some() { return Ok(GraphIndex(id)); } } std::cmp::Ordering::Equal => {} std::cmp::Ordering::Greater => { - if self.storage.graph.node(GraphIndex(id)).is_some() { + if self.graph.node(GraphIndex(id)).is_some() { return Ok(GraphIndex(id)); } } @@ -400,64 +296,12 @@ impl Db { Err(QueryError::from(format!("Id '{id}' not found"))) } - fn insert_value(&mut self, value: &DbValue) -> Result { - let mut index = DbValueIndex::new(); - - match value { - DbValue::Bytes(v) => { - index.set_type(db_value::BYTES_META_VALUE); - if index.set_value(v) { - return Ok(index); - } - } - DbValue::Int(v) => { - index.set_type(db_value::INT_META_VALUE); - index.set_value(&v.to_le_bytes()); - return Ok(index); - } - DbValue::Uint(v) => { - index.set_type(db_value::UINT_META_VALUE); - index.set_value(&v.to_le_bytes()); - return Ok(index); - } - DbValue::Float(v) => { - index.set_type(db_value::FLOAT_META_VALUE); - index.set_value(&v.to_f64().to_le_bytes()); - return Ok(index); - } - DbValue::String(v) => { - index.set_type(db_value::STRING_META_VALUE); - let bytes = v.as_bytes(); - if index.set_value(bytes) { - return Ok(index); - } - } - DbValue::VecInt(_) => { - index.set_type(db_value::VEC_INT_META_VALUE); - } - DbValue::VecUint(_) => { - index.set_type(db_value::VEC_UINT_META_VALUE); - } - DbValue::VecFloat(_) => { - index.set_type(db_value::VEC_FLOAT_META_VALUE); - } - DbValue::VecString(_) => { - index.set_type(db_value::VEC_STRING_META_VALUE); - } - } - - let dictionary_index = self.storage.dictionary.insert(value)?; - index.set_index(dictionary_index.0); - Ok(index) - } - fn node_edges( &self, graph_index: GraphIndex, ) -> Result, DbError> { let mut edges = vec![]; let node = self - .storage .graph .node(graph_index) .ok_or(DbError::from("Data integrity corrupted"))?; @@ -479,14 +323,13 @@ impl Db { fn remove_edge(&mut self, graph_index: GraphIndex) -> Result<(), DbError> { let (from, to) = { let edge = self - .storage .graph .edge(graph_index) .ok_or(DbError::from("Graph integrity corrupted"))?; (edge.index_from(), edge.index_to()) }; - self.storage.graph.remove_edge(graph_index)?; + self.graph.remove_edge(graph_index)?; self.undo_stack.push(Command::InsertEdge { from, to }); Ok(()) } @@ -502,51 +345,34 @@ impl Db { alias: alias.clone(), id: db_id, }); - self.storage.aliases.remove_key(&alias)?; - self.storage.aliases.remove_key(&alias)?; + self.aliases.remove_key(&alias)?; + self.aliases.remove_key(&alias)?; } for edge in self.node_edges(graph_index)? { - self.storage.graph.remove_edge(edge.0)?; + self.graph.remove_edge(edge.0)?; self.undo_stack.push(Command::InsertEdge { from: edge.1, to: edge.2, }); } - self.storage.graph.remove_node(graph_index)?; + self.graph.remove_node(graph_index)?; self.undo_stack.push(Command::InsertNode); Ok(()) } - fn remove_value(&mut self, value_index: DbValueIndex) -> Result<(), DbError> { - if !value_index.is_value() { - self.storage - .dictionary - .remove(DictionaryIndex(value_index.index()))?; - } - - Ok(()) - } - pub(crate) fn remove_keys(&mut self, db_id: DbId, keys: &[DbKey]) -> Result { let mut result = 0; - for key_value_index in self.storage.values.values(&db_id)? { - let key = self.value(&key_value_index.key)?; - - if keys.contains(&key) { - let value = self.value(&key_value_index.value)?; - self.remove_value(key_value_index.key)?; - self.remove_value(key_value_index.value)?; - + for key_value in self.values.values(&db_id)? { + if keys.contains(&key_value.key) { self.undo_stack.push(Command::InsertKeyValue { id: db_id, - key_value: DbKeyValue { key, value }, + key_value: key_value.clone(), }); - self.storage.values.remove_value(&db_id, &key_value_index)?; - - result += 1; + self.values.remove_value(&db_id, &key_value)?; + result -= 1; } } @@ -554,18 +380,14 @@ impl Db { } fn remove_all_values(&mut self, db_id: DbId) -> Result<(), QueryError> { - for key_value_index in self.storage.values.values(&db_id)? { - let key = self.value(&key_value_index.key)?; - let value = self.value(&key_value_index.value)?; - self.remove_value(key_value_index.key)?; - self.remove_value(key_value_index.value)?; + for key_value in self.values.values(&db_id)? { self.undo_stack.push(Command::InsertKeyValue { id: db_id, - key_value: DbKeyValue { key, value }, + key_value, }); } - self.storage.values.remove_key(&db_id)?; + self.values.remove_key(&db_id)?; Ok(()) } @@ -574,7 +396,6 @@ impl Db { let storage = Rc::new(RefCell::new(FileStorage::new(filename)?)); let graph_storage; let aliases_storage; - let dictionary_storage; let values_storage; let len = storage.borrow_mut().len()?; let index = storage @@ -584,19 +405,15 @@ impl Db { if let Ok(index) = index { graph_storage = DbGraph::from_storage(storage.clone(), index.graph)?; aliases_storage = DbIndexedMap::from_storage(storage.clone(), index.aliases)?; - dictionary_storage = - DictionaryStorage::from_storage(storage.clone(), index.dictionary)?; values_storage = MultiMapStorage::from_storage(storage.clone(), index.values)?; } else if len == 0 { storage.borrow_mut().insert(&DbStorageIndex::default())?; graph_storage = DbGraph::new(storage.clone())?; aliases_storage = DbIndexedMap::new(storage.clone())?; - dictionary_storage = DictionaryStorage::new(storage.clone())?; values_storage = MultiMapStorage::new(storage.clone())?; let db_storage_index = DbStorageIndex { graph: graph_storage.storage_index(), aliases: aliases_storage.storage_index(), - dictionary: dictionary_storage.storage_index(), values: values_storage.storage_index(), }; storage @@ -609,13 +426,10 @@ impl Db { } Ok(Self { - storage: DbStorage { - _storage: storage, - graph: graph_storage, - aliases: aliases_storage, - dictionary: dictionary_storage, - values: values_storage, - }, + _storage: storage, + graph: graph_storage, + aliases: aliases_storage, + values: values_storage, undo_stack: vec![], }) } @@ -626,22 +440,9 @@ mod tests { use super::*; use crate::test_utilities::test_file::TestFile; - #[test] - #[should_panic] - fn invalid_value_type() { - let test_file = TestFile::new(); - let db = Db::new(test_file.file_name()).unwrap(); - - let mut index = DbValueIndex::new(); - index.set_type(15_u8); - index.set_value(&1_u64.to_le_bytes()); - - db.value(&index).unwrap(); - } - #[test] fn db_storage_index_serialized_size() { - assert_eq!(DbStorageIndex::default().serialized_size(), 40); + assert_eq!(DbStorageIndex::default().serialized_size(), 32); } #[test] diff --git a/src/agdb/db/db_id.rs b/src/agdb/db/db_id.rs index 6694d1de3..aae7b61d8 100644 --- a/src/agdb/db/db_id.rs +++ b/src/agdb/db/db_id.rs @@ -1,5 +1,6 @@ use super::db_error::DbError; use crate::collections::vec::VecValue; +use crate::storage::Storage; use crate::utilities::serialize::Serialize; use crate::utilities::serialize::SerializeStatic; use crate::utilities::stable_hash::StableHash; @@ -13,25 +14,21 @@ impl StableHash for DbId { } } -impl Serialize for DbId { - fn serialize(&self) -> Vec { - self.0.serialize() +impl VecValue for DbId { + fn store(&self, _storage: &mut S) -> Result, DbError> { + Ok(self.0.serialize()) } - fn deserialize(bytes: &[u8]) -> Result { + fn load(_storage: &S, bytes: &[u8]) -> Result { Ok(Self(i64::deserialize(bytes)?)) } - fn serialized_size(&self) -> u64 { - self.0.serialized_size() + fn remove(_storage: &mut S, _bytes: &[u8]) -> Result<(), DbError> { + Ok(()) } -} -impl SerializeStatic for DbId {} - -impl VecValue for DbId { fn storage_len() -> u64 { - Self::serialized_size_static() + i64::serialized_size_static() } } @@ -61,13 +58,4 @@ mod tests { ids.sort(); assert_eq!(ids, vec![DbId(-1), DbId(0), DbId(3)]); } - - #[test] - fn serialize() { - let id = DbId(1); - assert_eq!(id.serialized_size(), 8); - let bytes = id.serialize(); - let other = DbId::deserialize(&bytes).unwrap(); - assert_eq!(id, other); - } } diff --git a/src/agdb/db/db_key_value.rs b/src/agdb/db/db_key_value.rs index 7cf3b4cbf..29383953a 100644 --- a/src/agdb/db/db_key_value.rs +++ b/src/agdb/db/db_key_value.rs @@ -1,7 +1,14 @@ +use super::db_error::DbError; +use super::db_value_index::DbValueIndex; +use crate::collections::vec::VecValue; +use crate::storage::Storage; +use crate::storage::StorageIndex; +use crate::utilities::serialize::Serialize; +use crate::utilities::serialize::SerializeStatic; use crate::DbKey; use crate::DbValue; -#[derive(Debug, Clone, PartialEq)] +#[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct DbKeyValue { pub key: DbKey, pub value: DbValue, @@ -20,6 +27,43 @@ where } } +impl VecValue for DbKeyValue { + fn store(&self, storage: &mut S) -> Result, DbError> { + let key_index = self.key.store_db_value(storage)?; + let value_index = self.value.store_db_value(storage)?; + Ok([key_index.value, value_index.value].concat()) + } + + fn load(storage: &S, bytes: &[u8]) -> Result { + let key_index = DbValueIndex::deserialize(bytes)?; + let value_index = + DbValueIndex::deserialize(&bytes[key_index.serialized_size() as usize..])?; + let key = DbValue::load_db_value(key_index, storage)?; + let value = DbValue::load_db_value(value_index, storage)?; + Ok(Self { key, value }) + } + + fn remove(storage: &mut S, bytes: &[u8]) -> Result<(), DbError> { + let key_index = DbValueIndex::deserialize(bytes)?; + let value_index = + DbValueIndex::deserialize(&bytes[key_index.serialized_size() as usize..])?; + + if !key_index.is_value() { + storage.remove(StorageIndex(key_index.index()))?; + } + + if !value_index.is_value() { + storage.remove(StorageIndex(value_index.index()))?; + } + + Ok(()) + } + + fn storage_len() -> u64 { + DbValueIndex::serialized_size_static() * 2 + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/agdb/db/db_key_value_index.rs b/src/agdb/db/db_key_value_index.rs deleted file mode 100644 index 21ddb6cde..000000000 --- a/src/agdb/db/db_key_value_index.rs +++ /dev/null @@ -1,68 +0,0 @@ -use super::db_error::DbError; -use super::db_value_index::DbValueIndex; -use crate::collections::vec::VecValue; -use crate::utilities::serialize::Serialize; -use crate::utilities::serialize::SerializeStatic; -use crate::utilities::stable_hash::StableHash; - -#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)] -pub(crate) struct DbKeyValueIndex { - pub(crate) key: DbValueIndex, - pub(crate) value: DbValueIndex, -} - -impl StableHash for DbKeyValueIndex { - fn stable_hash(&self) -> u64 { - [self.key.value, self.value.value].concat().stable_hash() - } -} - -impl Serialize for DbKeyValueIndex { - fn serialize(&self) -> Vec { - [self.key.value, self.value.value].concat() - } - - fn deserialize(bytes: &[u8]) -> Result { - Ok(Self { - key: DbValueIndex::deserialize(bytes)?, - value: DbValueIndex::deserialize( - &bytes[DbValueIndex::serialized_size_static() as usize..], - )?, - }) - } - - fn serialized_size(&self) -> u64 { - DbValueIndex::serialized_size_static() * 2 - } -} - -impl VecValue for DbKeyValueIndex { - fn storage_len() -> u64 { - DbValueIndex::serialized_size_static() * 2 - } -} - -#[cfg(test)] -mod tests { - use super::*; - use std::collections::hash_map::DefaultHasher; - use std::hash::Hash; - - #[test] - fn derived_from() { - let index = DbKeyValueIndex::default(); - assert_eq!(index, index.clone()); - - format!("{:?}", index); - - let mut hasher = DefaultHasher::new(); - DbKeyValueIndex::default().hash(&mut hasher); - - index.stable_hash(); - } - - #[test] - fn serialized_size() { - assert_eq!(DbKeyValueIndex::default().serialized_size(), 32); - } -} diff --git a/src/agdb/db/db_value.rs b/src/agdb/db/db_value.rs index 7864e3f9f..de61f6ecf 100644 --- a/src/agdb/db/db_value.rs +++ b/src/agdb/db/db_value.rs @@ -1,10 +1,8 @@ use super::db_error::DbError; use super::db_float::DbFloat; -use crate::collections::vec::VecValue; +use super::db_value_index::DbValueIndex; use crate::storage::Storage; use crate::storage::StorageIndex; -use crate::utilities::serialize::Serialize; -use crate::utilities::serialize::SerializeStatic; use crate::utilities::stable_hash::StableHash; #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] @@ -30,6 +28,111 @@ pub(crate) const VEC_UINT_META_VALUE: u8 = 7_u8; pub(crate) const VEC_FLOAT_META_VALUE: u8 = 8_u8; pub(crate) const VEC_STRING_META_VALUE: u8 = 9_u8; +impl DbValue { + pub(crate) fn load_db_value( + value_index: DbValueIndex, + storage: &S, + ) -> Result { + Ok(match value_index.get_type() { + BYTES_META_VALUE => { + if value_index.is_value() { + DbValue::Bytes(value_index.value().to_vec()) + } else { + DbValue::Bytes(storage.value_as_bytes(StorageIndex(value_index.index()))?) + } + } + INT_META_VALUE => { + let mut bytes = [0_u8; 8]; + bytes.copy_from_slice(value_index.value()); + DbValue::Int(i64::from_le_bytes(bytes)) + } + UINT_META_VALUE => { + let mut bytes = [0_u8; 8]; + bytes.copy_from_slice(value_index.value()); + DbValue::Uint(u64::from_le_bytes(bytes)) + } + FLOAT_META_VALUE => { + let mut bytes = [0_u8; 8]; + bytes.copy_from_slice(value_index.value()); + DbValue::Float(DbFloat::from(f64::from_le_bytes(bytes))) + } + STRING_META_VALUE => { + if value_index.is_value() { + DbValue::String(String::from_utf8_lossy(value_index.value()).to_string()) + } else { + DbValue::String(storage.value::(StorageIndex(value_index.index()))?) + } + } + VEC_INT_META_VALUE => { + DbValue::VecInt(storage.value::>(StorageIndex(value_index.index()))?) + } + VEC_UINT_META_VALUE => { + DbValue::VecUint(storage.value::>(StorageIndex(value_index.index()))?) + } + VEC_FLOAT_META_VALUE => { + DbValue::VecFloat(storage.value::>(StorageIndex(value_index.index()))?) + } + VEC_STRING_META_VALUE => { + DbValue::VecString(storage.value::>(StorageIndex(value_index.index()))?) + } + _ => panic!(), + }) + } + + pub(crate) fn store_db_value( + &self, + storage: &mut S, + ) -> Result { + let mut index = DbValueIndex::new(); + + match self { + DbValue::Bytes(v) => { + index.set_type(BYTES_META_VALUE); + if !index.set_value(v) { + index.set_index(storage.insert_bytes(v)?.0); + } + } + DbValue::Int(v) => { + index.set_type(INT_META_VALUE); + index.set_value(&v.to_le_bytes()); + } + DbValue::Uint(v) => { + index.set_type(UINT_META_VALUE); + index.set_value(&v.to_le_bytes()); + } + DbValue::Float(v) => { + index.set_type(FLOAT_META_VALUE); + index.set_value(&v.to_f64().to_le_bytes()); + } + DbValue::String(v) => { + index.set_type(STRING_META_VALUE); + let bytes = v.as_bytes(); + if !index.set_value(bytes) { + index.set_index(storage.insert(v)?.0); + } + } + DbValue::VecInt(v) => { + index.set_type(VEC_INT_META_VALUE); + index.set_index(storage.insert(v)?.0); + } + DbValue::VecUint(v) => { + index.set_type(VEC_UINT_META_VALUE); + index.set_index(storage.insert(v)?.0); + } + DbValue::VecFloat(v) => { + index.set_type(VEC_FLOAT_META_VALUE); + index.set_index(storage.insert(v)?.0); + } + DbValue::VecString(v) => { + index.set_type(VEC_STRING_META_VALUE); + index.set_index(storage.insert(v)?.0); + } + } + + Ok(index) + } +} + impl Default for DbValue { fn default() -> Self { Self::Int(0) @@ -150,93 +253,6 @@ impl From> for DbValue { } } -impl Serialize for DbValue { - fn deserialize(bytes: &[u8]) -> Result { - if bytes.is_empty() { - return Err(DbError::from("DbValue deserialization error: no data")); - } - - match bytes[0] { - BYTES_META_VALUE => Ok(DbValue::from(Vec::::deserialize(&bytes[1..])?)), - INT_META_VALUE => Ok(DbValue::from(i64::deserialize(&bytes[8..])?)), - UINT_META_VALUE => Ok(DbValue::from(u64::deserialize(&bytes[8..])?)), - FLOAT_META_VALUE => Ok(DbValue::from(DbFloat::deserialize(&bytes[8..])?)), - STRING_META_VALUE => Ok(DbValue::from(String::deserialize(&bytes[1..])?)), - VEC_INT_META_VALUE => Ok(DbValue::from(Vec::::deserialize(&bytes[1..])?)), - VEC_UINT_META_VALUE => Ok(DbValue::from(Vec::::deserialize(&bytes[1..])?)), - VEC_FLOAT_META_VALUE => Ok(DbValue::from(Vec::::deserialize(&bytes[1..])?)), - VEC_STRING_META_VALUE => Ok(DbValue::from(Vec::::deserialize(&bytes[1..])?)), - _ => Err(DbError::from("DbValue deserialization error: invalid data")), - } - } - - fn serialize(&self) -> Vec { - let mut bytes = Vec::::new(); - match self { - DbValue::Bytes(value) => { - bytes.reserve(1 + value.serialized_size() as usize); - bytes.push(BYTES_META_VALUE); - bytes.extend(value.serialize()); - } - DbValue::Int(value) => { - bytes.resize(16, 0_u8); - bytes[0] = INT_META_VALUE; - bytes[8..].copy_from_slice(&value.serialize()); - } - DbValue::Uint(value) => { - bytes.resize(16, 0_u8); - bytes[0] = UINT_META_VALUE; - bytes[8..].copy_from_slice(&value.serialize()); - } - DbValue::Float(value) => { - bytes.resize(16, 0_u8); - bytes[0] = FLOAT_META_VALUE; - bytes[8..].copy_from_slice(&value.serialize()); - } - DbValue::String(value) => { - bytes.reserve(1 + value.serialized_size() as usize); - bytes.push(STRING_META_VALUE); - bytes.extend(&value.serialize()); - } - DbValue::VecInt(value) => { - bytes.reserve(1 + value.serialized_size() as usize); - bytes.push(VEC_INT_META_VALUE); - bytes.extend(&value.serialize()); - } - DbValue::VecUint(value) => { - bytes.reserve(1 + value.serialized_size() as usize); - bytes.push(VEC_UINT_META_VALUE); - bytes.extend(&value.serialize()); - } - DbValue::VecFloat(value) => { - bytes.reserve(1 + value.serialized_size() as usize); - bytes.push(VEC_FLOAT_META_VALUE); - bytes.extend(&value.serialize()); - } - DbValue::VecString(value) => { - bytes.push(VEC_STRING_META_VALUE); - bytes.extend(&value.serialize()); - } - } - - bytes - } - - fn serialized_size(&self) -> u64 { - match self { - DbValue::Bytes(value) => 1 + value.serialized_size(), - DbValue::Int(value) => 8 + value.serialized_size(), - DbValue::Uint(value) => 8 + value.serialized_size(), - DbValue::Float(value) => 8 + value.serialized_size(), - DbValue::String(value) => 1 + value.serialized_size(), - DbValue::VecInt(value) => 1 + value.serialized_size(), - DbValue::VecUint(value) => 1 + value.serialized_size(), - DbValue::VecFloat(value) => 1 + value.serialized_size(), - DbValue::VecString(value) => 1 + value.serialized_size(), - } - } -} - impl StableHash for DbValue { fn stable_hash(&self) -> u64 { match self { @@ -253,37 +269,13 @@ impl StableHash for DbValue { } } -impl VecValue for DbValue { - fn store(&self, storage: &mut S) -> Result, DbError> { - let index = storage.insert(self)?; - Ok(index.serialize()) - } - - fn load(storage: &S, bytes: &[u8]) -> Result { - let storage_index = StorageIndex::deserialize(bytes)?; - storage.value::(storage_index) - } - - fn remove(storage: &mut S, bytes: &[u8]) -> Result<(), DbError> { - let storage_index = StorageIndex::deserialize(bytes)?; - storage.remove(storage_index) - } - - fn storage_len() -> u64 { - StorageIndex::serialized_size_static() - } -} - #[cfg(test)] mod tests { use super::*; - use crate::collections::vec::DbVec; use crate::storage::file_storage::FileStorage; use crate::test_utilities::test_file::TestFile; - use std::cell::RefCell; use std::cmp::Ordering; use std::collections::HashSet; - use std::rc::Rc; #[test] fn derived_from_eq() { @@ -393,170 +385,6 @@ mod tests { )); } - #[test] - fn serialize_bytes() { - let value = DbValue::from(vec![0_u8, 1_u8, 2_u8, 3_u8, 4_u8]); - let bytes = value.serialize(); - - assert_eq!(bytes.len() as u64, value.serialized_size()); - - let other = DbValue::deserialize(&bytes).unwrap(); - - assert_eq!(value, other); - } - - #[test] - fn serialize_i64() { - let value = DbValue::from(1_i64); - let bytes = value.serialize(); - - assert_eq!(bytes.len() as u64, value.serialized_size()); - - let other = DbValue::deserialize(&bytes).unwrap(); - - assert_eq!(value, other); - } - - #[test] - fn serialize_i64_max() { - let value = DbValue::from(i64::MAX); - let bytes = value.serialize(); - - assert_eq!(bytes.len() as u64, value.serialized_size()); - - let other = DbValue::deserialize(&bytes).unwrap(); - - assert_eq!(value, other); - } - - #[test] - fn serialize_i64_min() { - let value = DbValue::from(i64::MIN); - let bytes = value.serialize(); - - assert_eq!(bytes.len() as u64, value.serialized_size()); - - let other = DbValue::deserialize(&bytes).unwrap(); - - assert_eq!(value, other); - } - - #[test] - fn serialize_i64_negative() { - let value = DbValue::from(-1_i64); - let bytes = value.serialize(); - - assert_eq!(bytes.len() as u64, value.serialized_size()); - - let other = DbValue::deserialize(&bytes).unwrap(); - - assert_eq!(value, other); - } - - #[test] - fn serialize_u64() { - let value = DbValue::from(u64::MAX / 2); - let bytes = value.serialize(); - - assert_eq!(bytes.len() as u64, value.serialized_size()); - - let other = DbValue::deserialize(&bytes).unwrap(); - - assert_eq!(value, other); - } - - #[test] - fn serialize_db_float() { - let value = DbValue::from(0.1_f64 + 0.2_f64); - let bytes = value.serialize(); - - assert_eq!(bytes.len() as u64, value.serialized_size()); - - let other = DbValue::deserialize(&bytes).unwrap(); - - assert_eq!(value, other); - } - - #[test] - fn serialize_string() { - let value = DbValue::from("Hello, World!"); - let bytes = value.serialize(); - - assert_eq!(bytes.len() as u64, value.serialized_size()); - - let other = DbValue::deserialize(&bytes).unwrap(); - - assert_eq!(value, other); - } - - #[test] - fn serialize_vec_int() { - let value = DbValue::from(vec![i64::MAX, 0_i64, i64::MIN]); - let bytes = value.serialize(); - - assert_eq!(bytes.len() as u64, value.serialized_size()); - - let actual = DbValue::deserialize(&bytes).unwrap(); - - assert_eq!(value, actual); - } - - #[test] - fn serialize_vec_uint() { - let value = DbValue::from(vec![u64::MAX, 0_u64, u64::MIN]); - let bytes = value.serialize(); - - assert_eq!(bytes.len() as u64, value.serialized_size()); - - let actual = DbValue::deserialize(&bytes).unwrap(); - - assert_eq!(value, actual); - } - - #[test] - fn serialize_vec_float() { - let value = DbValue::from(vec![0.1_f64 + 0.2_f64, -0.0_f64, std::f64::consts::PI]); - let bytes = value.serialize(); - - assert_eq!(bytes.len() as u64, value.serialized_size()); - - let actual = DbValue::deserialize(&bytes).unwrap(); - - assert_eq!(value, actual); - } - - #[test] - fn serialize_vec_string() { - let value = DbValue::from(vec!["Hello", ", ", "World", "!"]); - let bytes = value.serialize(); - - assert_eq!(bytes.len() as u64, value.serialized_size()); - - let actual = DbValue::deserialize(&bytes).unwrap(); - - assert_eq!(value, actual); - } - - #[test] - fn serialize_no_data() { - let bytes = Vec::::new(); - - assert_eq!( - DbValue::deserialize(&bytes), - Err(DbError::from("DbValue deserialization error: no data")) - ); - } - - #[test] - fn serialize_invalid_data() { - let bytes = vec![255_u8]; - - assert_eq!( - DbValue::deserialize(&bytes), - Err(DbError::from("DbValue deserialization error: invalid data")) - ); - } - #[test] fn stable_hash() { assert_ne!(DbValue::from(vec![1_u8]).stable_hash(), 0); @@ -571,29 +399,11 @@ mod tests { } #[test] - fn storage_value() { + #[should_panic] + fn bad_deserialization() { let test_file = TestFile::new(); - let storage = Rc::new(RefCell::new( - FileStorage::new(test_file.file_name()).unwrap(), - )); - - let mut values: Vec = vec![ - 1.1.into(), - "Hello, World! Not a short string".into(), - vec!["Hello", ",", "World", "!"].into(), - ]; - - let mut vec = DbVec::::new(storage).unwrap(); - - for value in &values { - vec.push(value).unwrap(); - } - - values.remove(1); - vec.remove(1).unwrap(); - - let actual: Vec = vec.iter().collect(); + let storage = FileStorage::new(&test_file.filename).unwrap(); - assert_eq!(values, actual); + let _ = DbValue::load_db_value(DbValueIndex::new(), &storage); } } diff --git a/src/agdb/graph.rs b/src/agdb/graph.rs index 2bca285f2..1704faf4b 100644 --- a/src/agdb/graph.rs +++ b/src/agdb/graph.rs @@ -1,5 +1,4 @@ use crate::collections::vec::DbVec; -use crate::collections::vec::VecValue; use crate::db::db_error::DbError; use crate::storage::file_storage::FileStorage; use crate::storage::Storage; @@ -47,28 +46,6 @@ impl StableHash for GraphIndex { } } -impl Serialize for GraphIndex { - fn serialize(&self) -> Vec { - self.0.serialize() - } - - fn deserialize(bytes: &[u8]) -> Result { - Ok(Self(i64::deserialize(bytes)?)) - } - - fn serialized_size(&self) -> u64 { - self.0.serialized_size() - } -} - -impl SerializeStatic for GraphIndex {} - -impl VecValue for GraphIndex { - fn storage_len() -> u64 { - Self::serialized_size_static() - } -} - pub trait GraphData { fn capacity(&self) -> Result; fn commit(&mut self, id: u64) -> Result<(), DbError>; @@ -771,19 +748,6 @@ mod tests { let _ = GraphIndex(10).stable_hash(); } - #[test] - fn index_serialization() { - let index = GraphIndex(10); - let bytes = index.serialize(); - let other = GraphIndex::deserialize(&bytes).unwrap(); - - assert_eq!(index, other); - assert_eq!( - GraphIndex::storage_len(), - GraphIndex::serialized_size_static() - ); - } - #[test] fn ordering() { let mut indexes = vec![ @@ -816,11 +780,6 @@ mod tests { .serialized_size(), StorageIndex::default().serialized_size() * 4 ); - - assert_eq!( - GraphIndex::default().serialized_size(), - i64::serialized_size_static() - ); } #[test] diff --git a/src/agdb/query/insert_edges_query.rs b/src/agdb/query/insert_edges_query.rs index 72404da88..62abde260 100644 --- a/src/agdb/query/insert_edges_query.rs +++ b/src/agdb/query/insert_edges_query.rs @@ -58,7 +58,7 @@ impl InsertEdgesQuery { ids.push(db_id); for key_value in key_values { - db.insert_key_value(db_id, &key_value.key, &key_value.value)?; + db.insert_key_value(db_id, key_value)?; } } @@ -83,7 +83,7 @@ impl InsertEdgesQuery { ids.push(db_id); for key_value in values[index] { - db.insert_key_value(db_id, &key_value.key, &key_value.value)?; + db.insert_key_value(db_id, key_value)?; } index += 1; diff --git a/src/agdb/query/insert_nodes_query.rs b/src/agdb/query/insert_nodes_query.rs index 34b74302e..1de6b8618 100644 --- a/src/agdb/query/insert_nodes_query.rs +++ b/src/agdb/query/insert_nodes_query.rs @@ -29,7 +29,7 @@ impl QueryMut for InsertNodesQuery { } for key_value in *key_values { - db.insert_key_value(db_id, &key_value.key, &key_value.value)?; + db.insert_key_value(db_id, key_value)?; } } diff --git a/src/agdb/query/insert_values_query.rs b/src/agdb/query/insert_values_query.rs index e87c2b6fc..24bb8206c 100644 --- a/src/agdb/query/insert_values_query.rs +++ b/src/agdb/query/insert_values_query.rs @@ -19,7 +19,7 @@ impl QueryMut for InsertValuesQuery { for id in ids { let db_id = db.db_id(id)?; for key_value in values { - db.insert_key_value(db_id, &key_value.key, &key_value.value)?; + db.insert_key_value(db_id, key_value)?; result.result += 1; } } @@ -32,7 +32,7 @@ impl QueryMut for InsertValuesQuery { for (id, values) in ids.iter().zip(values) { let db_id = db.db_id(id)?; for key_value in values { - db.insert_key_value(db_id, &key_value.key, &key_value.value)?; + db.insert_key_value(db_id, key_value)?; result.result += 1; } } diff --git a/src/agdb/query/remove_values_query.rs b/src/agdb/query/remove_values_query.rs index dc642745d..d346ccf06 100644 --- a/src/agdb/query/remove_values_query.rs +++ b/src/agdb/query/remove_values_query.rs @@ -13,7 +13,7 @@ impl QueryMut for RemoveValuesQuery { QueryIds::Ids(ids) => { for id in ids { let db_id = db.db_id(id)?; - result.result -= db.remove_keys(db_id, &self.0.keys)?; + result.result += db.remove_keys(db_id, &self.0.keys)?; } Ok(()) } diff --git a/src/agdb/query/select_query.rs b/src/agdb/query/select_query.rs index 11e513413..3e693cedf 100644 --- a/src/agdb/query/select_query.rs +++ b/src/agdb/query/select_query.rs @@ -3,7 +3,6 @@ use super::query_ids::QueryIds; use super::Query; use crate::Db; use crate::DbElement; -use crate::DbKeyValue; use crate::QueryError; use crate::QueryResult; @@ -27,20 +26,11 @@ impl SelectQuery { fn select_id(query_id: &QueryId, db: &Db, result: &mut QueryResult) -> Result<(), QueryError> { let db_id = db.db_id(query_id)?; - let mut element = DbElement { - index: db_id, - values: vec![], - }; - - for key_value_index in db.values(db_id)? { - let key = db.value(&key_value_index.key)?; - let value = db.value(&key_value_index.value)?; - - element.values.push(DbKeyValue { key, value }); - } - result.result += 1; - result.elements.push(element); + result.elements.push(DbElement { + index: db_id, + values: db.values(db_id)?, + }); Ok(()) } diff --git a/src/agdb/test_utilities/collision_value.rs b/src/agdb/test_utilities/collision_value.rs index 913faeb7d..147ef24fe 100644 --- a/src/agdb/test_utilities/collision_value.rs +++ b/src/agdb/test_utilities/collision_value.rs @@ -5,7 +5,7 @@ use crate::utilities::serialize::Serialize; use crate::utilities::serialize::SerializeStatic; use crate::utilities::stable_hash::StableHash; -#[derive(Clone, Debug, Default, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct CollisionValue { pub value: T, } diff --git a/tests/db_test.rs b/tests/db_test.rs index a1aba6e34..75ca9a0e6 100644 --- a/tests/db_test.rs +++ b/tests/db_test.rs @@ -10,6 +10,18 @@ use test_file::TestFile; #[test] fn data_persistence() { let test_file = TestFile::new(); + let values = vec![ + ("key", "String that is much longer than 15 characters").into(), + (-10_i64, 2000000000000_i64).into(), + (10_u64, 1.1_f64).into(), + (vec!["Some", "List"], vec![1_u64, 2_u64]).into(), + ( + vec![-1_i64, -2_i64, -3_i64], + vec![-3.3_f64, -3.4_f64, -720.984_f64], + ) + .into(), + (vec![3_u8; 5], vec![15_u8; 20]).into(), + ]; { let mut db = Db::new(test_file.file_name()).unwrap(); @@ -17,7 +29,7 @@ fn data_persistence() { &QueryBuilder::insert() .nodes() .aliases(&["alias".into(), "alias2".into()]) - .values_uniform(&[("key", 100).into()]) + .values_uniform(&values) .query(), ) .unwrap(); @@ -36,11 +48,11 @@ fn data_persistence() { &[ DbElement { index: DbId(1), - values: vec![("key", 100).into()], + values: values.clone(), }, DbElement { index: DbId(2), - values: vec![("key", 100).into()], + values: values.clone(), }, DbElement { index: DbId(-3), @@ -64,11 +76,11 @@ fn data_persistence() { &[ DbElement { index: DbId(1), - values: vec![("key", 100).into()], + values: values.clone(), }, DbElement { index: DbId(2), - values: vec![("key", 100).into()], + values, }, DbElement { index: DbId(-3),