db/repo/
vertex_property.rs

1use std::collections::HashMap;
2
3use crate::interface::KeyValuePair;
4use crate::storage::Transaction;
5use crate::util::{
6	build_byte_map, build_bytes, build_sized, build_usize_from_bytes, concat_bytes, Component,
7};
8use crate::{Error, SimpleTransaction};
9use solomon_gremlin::structure::VertexPropertyMap;
10use solomon_gremlin::{GValue, VertexProperty, GID};
11
12impl_repository!(VertexPropertyRepository(VertexProperty));
13
14fn build_vertex_property_value(value: &GValue) -> Vec<u8> {
15	// let len = Component::GValue(value).len() + Component::GValueType(value).len();
16	build_bytes(&[Component::GValueType(value), Component::GValue(value)]).unwrap()
17}
18
19fn build_vertex_property_key(vertex_id: &GID, id: &GID, label: &GValue) -> Vec<u8> {
20	concat_bytes(vec![
21		build_sized(Component::Gid(vertex_id)),
22		build_sized(Component::GValue(label)),
23		build_sized(Component::Gid(id)),
24	])
25}
26
27impl<'a> VertexPropertyRepository<'a> {
28	/// The property()-step is used to add properties to the elements of the graph (sideEffect).
29	/// Unlike addV() and addE(), property() is a full sideEffect step in that it does not return
30	/// the property it created, but the element that streamed into it. Moreover, if property()
31	/// follows an addV() or addE(), then it is "folded" into the previous step to enable vertex
32	/// and edge creation with all its properties in one creation operation.
33	pub async fn property(
34		&self,
35		tx: &mut Transaction,
36		vertex_id: &GID,
37		id: &GID,
38		label: &GValue,
39		value: &GValue,
40	) -> Result<VertexProperty, Error> {
41		let cf = self.cf();
42		let key = build_vertex_property_key(vertex_id, id, label);
43		let val = self.append_value(tx, vertex_id, id, label, value).await.unwrap();
44		tx.set(cf, key.to_vec(), val).await.unwrap();
45		let label = label.get::<String>().unwrap();
46		Ok(VertexProperty::new(vertex_id, label, value.clone()))
47	}
48
49	async fn append_value(
50		&self,
51		tx: &mut Transaction,
52		vertex_id: &GID,
53		id: &GID,
54		label: &GValue,
55		value: &GValue,
56	) -> Result<Vec<u8>, Error> {
57		let cf = self.cf();
58		let val = build_vertex_property_value(value);
59		let key = build_vertex_property_key(vertex_id, id, label);
60
61		let get_current_val = tx.get(cf, key.to_vec()).await;
62		match get_current_val {
63			Ok(v) => {
64				let existing_val = v.unwrap_or_default();
65				Ok([existing_val, val].concat())
66			}
67			Err(_) => Ok(vec![]),
68		}
69	}
70
71	/// Method to iterate the pairs of byte data
72	fn iterate(
73		&self,
74		iterator: Vec<Result<KeyValuePair, Error>>,
75	) -> Result<VertexPropertyMap, Error> {
76		let mut map = HashMap::<String, Vec<VertexProperty>>::new();
77		iterator.iter().for_each(|p| {
78			let (k, v) = p.as_ref().unwrap();
79			// Handle deserializing and rebuild vertex stream
80			let bytemap = &build_byte_map(vec!["vertex_id", "label", "id"], k.to_vec());
81			let label = String::from_utf8(bytemap.get("label").unwrap().to_vec()).unwrap();
82			let gid = GID::Bytes(bytemap.get("id").unwrap().to_vec());
83			// Handle deserializing GValue
84			let variant = build_usize_from_bytes(v[..1].to_vec());
85			let value = GValue::from_bytes(variant, v[1..].to_vec());
86			let property = VertexProperty::new(gid, label.clone(), value);
87			map.entry(label).or_default().push(property);
88		});
89
90		Ok(map)
91	}
92
93	/// Method to iterate the pairs of byte data with prefix as vertex id
94	pub async fn iterate_from_vertex(
95		&self,
96		tx: &Transaction,
97		vertex_id: &GID,
98	) -> Result<VertexPropertyMap, Error> {
99		let cf = self.cf();
100		let prefix = concat_bytes(vec![build_sized(Component::Gid(vertex_id))]);
101		let iterator = tx.prefix_iterate(cf, prefix).await.unwrap();
102		self.iterate(iterator)
103	}
104
105	pub async fn iterate_from_label(
106		&self,
107		tx: &Transaction,
108		vertex_id: &GID,
109		label: &GValue,
110	) -> Result<VertexPropertyMap, Error> {
111		let cf = self.cf();
112		let prefix = concat_bytes(vec![
113			build_sized(Component::Gid(vertex_id)),
114			build_sized(Component::GValue(label)),
115		]);
116		let iterator = tx.prefix_iterate(cf, prefix).await.unwrap();
117		self.iterate(iterator)
118	}
119}