From d32aec22651f4e60e513ce1ed89bf357f36ff6b1 Mon Sep 17 00:00:00 2001 From: Chung Quan Tin Date: Sat, 12 Nov 2022 11:24:44 +0700 Subject: [PATCH] Add relationship controller & refractor test dir --- db/src/controller/label.rs | 35 +++++++-------- db/src/controller/property.rs | 45 ++++--------------- db/src/controller/relationship.rs | 67 +++++++++++++++++++++++----- db/src/controller/vertex.rs | 65 ++++++++------------------- db/src/lib.rs | 2 +- db/src/model/graph/account.rs | 5 --- db/src/model/graph/property.rs | 10 ++--- db/src/model/graph/relationship.rs | 20 ++++----- db/src/tests/label_test.rs | 23 ++++++++++ db/src/tests/mod.rs | 10 ++++- db/src/tests/property_test.rs | 25 +++++++++++ db/src/tests/relationship_test.rs | 70 ++++++++++++++++++++++++++++++ db/src/tests/vertex_test.rs | 39 +++++++++++++++++ db/src/util/byte.rs | 56 +++++++----------------- 14 files changed, 295 insertions(+), 177 deletions(-) create mode 100644 db/src/tests/label_test.rs create mode 100644 db/src/tests/property_test.rs create mode 100644 db/src/tests/relationship_test.rs create mode 100644 db/src/tests/vertex_test.rs diff --git a/db/src/controller/label.rs b/db/src/controller/label.rs index 624bd0a..34f0a54 100644 --- a/db/src/controller/label.rs +++ b/db/src/controller/label.rs @@ -1,5 +1,7 @@ -use crate::util::{build_bytes, from_uuid_bytes, Component}; -use crate::{DatastoreAdapter, Error, Label, SimpleTransaction}; +use crate::util::{ + build_bytes, build_meta, deserialize_data_with_meta, from_uuid_bytes, Component, +}; +use crate::{AccountDiscriminator, DatastoreAdapter, Error, Label, SimpleTransaction}; impl_controller!(LabelController("labels:v1")); @@ -19,7 +21,9 @@ impl LabelController { let cf = self.get_cf(); let key = build_bytes(&[Component::Uuid(label.id)]).unwrap(); - let val = name.as_bytes(); + let discriminator = AccountDiscriminator::Label.serialize(); + let meta = &build_meta(1, name.len()); + let val = [discriminator, meta.to_vec(), name.as_bytes().to_vec()].concat(); tx.set(cf, key, val).await.unwrap(); tx.commit().await.unwrap(); @@ -40,23 +44,16 @@ impl LabelController { let tx = self.config.ds.transaction(false).unwrap(); let cf = self.get_cf(); - let val = tx.get(cf, id.to_vec()).await.unwrap(); - match val { - Some(v) => Ok(Label { - id: from_uuid_bytes(&id).unwrap(), - name: String::from_utf8(v).unwrap(), - }), + let raw = tx.get(cf, id.to_vec()).await.unwrap(); + match raw { + Some(r) => { + let (data, _, _) = deserialize_data_with_meta(r, true).unwrap(); + Ok(Label { + id: from_uuid_bytes(&id).unwrap(), + name: String::from_utf8(data[0].to_vec()).unwrap(), + }) + } None => panic!("No label value"), } } } - -// #[cfg(feature = "test-suite")] -#[cfg(test)] -#[tokio::test] -async fn should_create_label() { - let lc = LabelController::default(); - let res = lc.create_label("Person").await.unwrap(); - let label = lc.get_label(res.id.as_bytes().to_vec()).await.unwrap(); - assert_eq!(label, res); -} diff --git a/db/src/controller/property.rs b/db/src/controller/property.rs index f4d1ca4..bf9391c 100644 --- a/db/src/controller/property.rs +++ b/db/src/controller/property.rs @@ -1,5 +1,5 @@ -use crate::util::{build_bytes, build_offset, deserialize_byte_data, from_uuid_bytes, Component}; -use crate::{DatastoreAdapter, Error, Property, PropertyVariant, SimpleTransaction}; +use crate::util::{build_bytes, build_meta, deserialize_byte_data, from_uuid_bytes, Component}; +use crate::{DatastoreAdapter, Error, PropType, Property, SimpleTransaction}; impl_controller!(PropertyController("properties:v1")); @@ -12,22 +12,18 @@ impl Default for PropertyController { } impl PropertyController { - pub async fn create_property( - &self, - name: &str, - variant: PropertyVariant, - ) -> Result { + pub async fn create_property(&self, name: &str, variant: PropType) -> Result { let mut tx = self.config.ds.transaction(true).unwrap(); let cf = self.get_cf(); // First four bytes are the property - let serialized_variant = bincode::serialize::(&variant).unwrap(); + let serialized_variant = bincode::serialize::(&variant).unwrap(); let property = Property::new(name, variant).unwrap(); - let property_offset = &build_offset(1, serialized_variant.len()); + let property_meta = &build_meta(1, serialized_variant.len()); let name = name.as_bytes(); - let name_offset = &build_offset(1, name.len()); + let name_meta = &build_meta(1, name.len()); // Dynamic length string will be concatenated at the end - let val = [property_offset, &serialized_variant, name_offset, name].concat(); + let val = [property_meta, &serialized_variant, name_meta, name].concat(); let key = build_bytes(&[Component::Uuid(property.id)]).unwrap(); tx.set(cf, key, val).await.unwrap(); @@ -37,7 +33,7 @@ impl PropertyController { pub async fn create_properties( &self, - properties: Vec<(&str, PropertyVariant)>, + properties: Vec<(&str, PropType)>, ) -> Result, Error> { let mut result = vec![]; for (name, variant) in properties { @@ -59,7 +55,7 @@ impl PropertyController { let name = &deserialized[1].0.first().unwrap(); let name = String::from_utf8(name.to_vec()).unwrap(); - let t = bincode::deserialize::(property).unwrap(); + let t = bincode::deserialize::(property).unwrap(); Ok(Property { id: from_uuid_bytes(&id).unwrap(), name, @@ -70,26 +66,3 @@ impl PropertyController { } } } - -#[cfg(test)] -#[tokio::test] -async fn should_create_property() { - let pc = PropertyController::default(); - let res = pc.create_property("Name", PropertyVariant::String).await.unwrap(); - let property = pc.get_property(res.id.as_bytes().to_vec()).await.unwrap(); - assert_eq!(property, res); -} - -#[cfg(test)] -#[tokio::test] -async fn should_create_properties() { - let pc = PropertyController::default(); - let properties = pc - .create_properties(vec![ - ("name", PropertyVariant::String), - ("age", PropertyVariant::UInt128), - ]) - .await - .unwrap(); - assert_eq!(properties.len(), 2); -} diff --git a/db/src/controller/relationship.rs b/db/src/controller/relationship.rs index 67d571d..753ab5a 100644 --- a/db/src/controller/relationship.rs +++ b/db/src/controller/relationship.rs @@ -1,9 +1,10 @@ use std::collections::HashMap; - use uuid::Uuid; -use crate::util::{build_bytes, Component}; -use crate::{DatastoreAdapter, Error, Identifier, Relationship, SimpleTransaction}; +use crate::util::{build_bytes, deserialize_data_with_meta, from_uuid_bytes, Component}; +use crate::{ + AccountDiscriminator, DatastoreAdapter, Error, Identifier, Relationship, SimpleTransaction, +}; impl_controller!(RelationshipController("relationships:v1")); @@ -16,29 +17,73 @@ impl Default for RelationshipController { } impl RelationshipController { - pub async fn create_property( + pub async fn create_relationship( &self, - s_node: Uuid, - t_node: Uuid, + source_vertex: Uuid, + target_vertex: Uuid, t: &str, props: HashMap>, ) -> Result { let mut tx = self.config.ds.transaction(true).unwrap(); + let prop_components = + props.iter().map(|(id, val)| Component::Property(id, val)).collect::>(); let cf = self.get_cf(); let t_id = Identifier::new(t.to_string()).unwrap(); let key = build_bytes(&[ - Component::Uuid(s_node), - Component::Uuid(s_node), + Component::Uuid(source_vertex), Component::Identifier(&t_id), - Component::Uuid(t_node), + Component::Uuid(target_vertex), ]) .unwrap(); - let relationship = Relationship::new(s_node, t_node, t_id, props).unwrap(); - let val = []; + + // Handle byte concatenate for property components + let _prop_discriminator = AccountDiscriminator::Property.serialize(); + let _props = &build_bytes(&prop_components).unwrap(); + // (Property discriminator, Property byte array - meta for each property generated) + let (p_dis, p) = (_prop_discriminator.as_slice(), _props.as_slice()); + let props_concat = [p_dis, p].concat(); + + let val = [props_concat].concat(); tx.set(cf, key, val).await.unwrap(); tx.commit().await.unwrap(); + + let relationship = Relationship::new(source_vertex, target_vertex, t_id, props).unwrap(); + Ok(relationship) + } + + pub async fn get_relationship( + &self, + source_vertex: Uuid, + target_vertex: Uuid, + t: &str, + ) -> Result { + let tx = self.config.ds.transaction(false).unwrap(); + let cf = self.get_cf(); + let t_id = Identifier::new(t.to_string()).unwrap(); + let key = build_bytes(&[ + Component::Uuid(source_vertex), + Component::Identifier(&t_id), + Component::Uuid(target_vertex), + ]) + .unwrap(); + + let mut props = HashMap::default(); + let raw_relationship = tx.get(cf, key).await.unwrap(); + match raw_relationship { + Some(r) => { + let (props_bytes, _, _) = deserialize_data_with_meta(r, true).unwrap(); + let uuid_len = Component::Uuid(Uuid::nil()).len(); + for slice in props_bytes { + let (uuid, value) = (&slice[..uuid_len], &slice[uuid_len..]); + props.insert(from_uuid_bytes(uuid).unwrap(), value.to_vec()); + } + } + None => panic!("No relationship found"), + } + + let relationship = Relationship::new(source_vertex, target_vertex, t_id, props).unwrap(); Ok(relationship) } } diff --git a/db/src/controller/vertex.rs b/db/src/controller/vertex.rs index 5e06993..2d9e62d 100644 --- a/db/src/controller/vertex.rs +++ b/db/src/controller/vertex.rs @@ -2,8 +2,7 @@ use std::collections::HashMap; use crate::{ model::adapter::DatastoreAdapter, - serialize_discriminator, - util::{build_bytes, build_offset, deserialize_byte_data, from_uuid_bytes, Component}, + util::{build_bytes, build_meta, deserialize_byte_data, from_uuid_bytes, Component}, AccountDiscriminator, Error, Label, SimpleTransaction, Vertex, }; @@ -21,6 +20,14 @@ impl Default for VertexController { impl VertexController { /// # Create a new vertex from labels and properties + /// ## Description + /// Because Vertex has multiple dynamic sized attributes: + /// - labels: Vec