Skip to content

Commit

Permalink
Add relationship controller & refractor test dir
Browse files Browse the repository at this point in the history
  • Loading branch information
chungquantin committed Nov 12, 2022
1 parent 5406bab commit d32aec2
Show file tree
Hide file tree
Showing 14 changed files with 295 additions and 177 deletions.
35 changes: 16 additions & 19 deletions db/src/controller/label.rs
Original file line number Diff line number Diff line change
@@ -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"));

Expand All @@ -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();
Expand All @@ -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);
}
45 changes: 9 additions & 36 deletions db/src/controller/property.rs
Original file line number Diff line number Diff line change
@@ -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"));

Expand All @@ -12,22 +12,18 @@ impl Default for PropertyController {
}

impl PropertyController {
pub async fn create_property(
&self,
name: &str,
variant: PropertyVariant,
) -> Result<Property, Error> {
pub async fn create_property(&self, name: &str, variant: PropType) -> Result<Property, Error> {
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::<PropertyVariant>(&variant).unwrap();
let serialized_variant = bincode::serialize::<PropType>(&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();
Expand All @@ -37,7 +33,7 @@ impl PropertyController {

pub async fn create_properties(
&self,
properties: Vec<(&str, PropertyVariant)>,
properties: Vec<(&str, PropType)>,
) -> Result<Vec<Property>, Error> {
let mut result = vec![];
for (name, variant) in properties {
Expand All @@ -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::<PropertyVariant>(property).unwrap();
let t = bincode::deserialize::<PropType>(property).unwrap();
Ok(Property {
id: from_uuid_bytes(&id).unwrap(),
name,
Expand All @@ -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);
}
67 changes: 56 additions & 11 deletions db/src/controller/relationship.rs
Original file line number Diff line number Diff line change
@@ -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"));

Expand All @@ -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<Uuid, Vec<u8>>,
) -> Result<Relationship, Error> {
let mut tx = self.config.ds.transaction(true).unwrap();
let prop_components =
props.iter().map(|(id, val)| Component::Property(id, val)).collect::<Vec<Component>>();

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<Relationship, Error> {
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)
}
}
65 changes: 18 additions & 47 deletions db/src/controller/vertex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

Expand All @@ -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<Label>
/// - props: HashMap<Uuid, Vec<u8>>
/// It will be a bit more complicated.
///
/// Data will be store in Vertex as
/// + label_discriminator | label_meta | label data
pub async fn create_vertex(
&self,
labels: Vec<Label>,
Expand All @@ -35,19 +42,21 @@ impl VertexController {
let label_components =
labels.iter().map(|l| Component::Uuid(l.id)).collect::<Vec<Component>>();
let prop_components =
props.iter().map(|p| Component::Property(p.0, p.1)).collect::<Vec<Component>>();
props.iter().map(|(id, val)| Component::Property(id, val)).collect::<Vec<Component>>();

// Handle byte concatenate for label components
let _label_discriminator = serialize_discriminator(AccountDiscriminator::Label).unwrap();
let label_discriminator = AccountDiscriminator::Label.serialize();
let _labels = build_bytes(&label_components).unwrap();
let _label_offset = &build_offset(ll, uuid_len);
let (l_dis, l, l_offset) =
(_label_discriminator.as_slice(), _label_offset.as_slice(), _labels.as_slice());
let labels_concat = [l_dis, l, l_offset].concat();
let label_meta = &build_meta(ll, uuid_len);
// (Label discriminator, Label byte array, Label metadata)
let (l_dis, l, l_meta) =
(label_discriminator.as_slice(), label_meta.as_slice(), _labels.as_slice());
let labels_concat = [l_dis, l, l_meta].concat();

// Handle byte concatenate for property components
let _prop_discriminator = AccountDiscriminator::Property.serialize();
let _props = &build_bytes(&prop_components).unwrap();
let _prop_discriminator = serialize_discriminator(AccountDiscriminator::Property).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();

Expand Down Expand Up @@ -105,41 +114,3 @@ impl VertexController {
}
}
}

// #[cfg(feature = "test-suite")]
#[cfg(test)]
#[tokio::test]
async fn should_create_label() {
use crate::{LabelController, PropertyController, PropertyVariant};

let vc = VertexController::default();
let lc = LabelController::default();
let pc = PropertyController::default();

let raw_labels = ["Person", "Student", "Employee"];
let properties = pc
.create_properties(vec![
("name", PropertyVariant::String),
("age", PropertyVariant::UInt128),
("addresses", PropertyVariant::VecString),
])
.await
.unwrap();
let labels = lc.create_labels(raw_labels.to_vec()).await.unwrap();
let res = vc
.create_vertex(
labels,
HashMap::from([
(properties[0].id, "example name 1234".as_bytes().to_vec()),
(properties[1].id, Vec::from([15])),
(properties[2].id, ["address 1", "address 2"].concat().as_bytes().to_vec()),
]),
)
.await
.unwrap();
assert_eq!(res.labels.len(), raw_labels.len());

let vertex = vc.get_vertex(res.id.as_bytes().to_vec()).await.unwrap();
assert_eq!(vertex, res);
assert_eq!(vertex.labels.len(), raw_labels.len());
}
2 changes: 1 addition & 1 deletion db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ mod util;
pub use crate::storage::kvs::CassandraDBAdapter;
#[cfg(feature = "kv-rocksdb")]
pub use crate::storage::kvs::RocksDBAdapter;
#[cfg(feature = "test-suite")]
// #[cfg(feature = "test-suite")]
#[macro_use]
pub mod tests;

Expand Down
5 changes: 0 additions & 5 deletions db/src/model/graph/account.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use bincode::Error;
use serde::{Deserialize, Serialize};

#[derive(PartialEq, Serialize, Deserialize, Eq, Debug, Clone)]
Expand All @@ -15,7 +14,3 @@ impl AccountDiscriminator {
bincode::serialize(self).unwrap()
}
}

pub fn serialize_discriminator(ad: AccountDiscriminator) -> Result<Vec<u8>, Error> {
bincode::serialize(&ad)
}
10 changes: 5 additions & 5 deletions db/src/model/graph/property.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use uuid::Uuid;
use crate::Error;

#[derive(PartialEq, Serialize, Deserialize, Eq, Debug, Clone)]
pub enum PropertyVariant {
pub enum PropType {
Unknown = 0,
String = 1,
UInt32 = 2,
Expand All @@ -17,9 +17,9 @@ pub enum PropertyVariant {
VecUint128 = 9,
}

impl Default for PropertyVariant {
impl Default for PropType {
fn default() -> Self {
PropertyVariant::Unknown
PropType::Unknown
}
}

Expand All @@ -29,12 +29,12 @@ impl Default for PropertyVariant {
#[derive(PartialEq, Eq, Debug, Clone, Default)]
pub struct Property {
pub id: Uuid,
pub t: PropertyVariant,
pub t: PropType,
pub name: String,
}

impl Property {
pub fn new(name: &str, t: PropertyVariant) -> Result<Self, Error> {
pub fn new(name: &str, t: PropType) -> Result<Self, Error> {
Ok(Property {
id: Uuid::new_v4(),
name: name.to_string(),
Expand Down
Loading

0 comments on commit d32aec2

Please sign in to comment.