use std::collections::HashMap;
use crate::types::{
gvalue::Primitive, AdjacentEdgeCursor, AdjacentEdgesOptions, CanonicalEdgeKey, Direction, Edge, EdgeKey, LabelId,
StoreError, Vertex, VertexKey,
};
pub trait GraphSnapshot {
fn get_vertex(&mut self, key: VertexKey) -> Result<Option<Vertex>, StoreError>;
fn get_vertices(&mut self, keys: &[VertexKey]) -> Result<Vec<Vertex>, StoreError> {
let mut out = Vec::with_capacity(keys.len());
for &k in keys {
if let Some(v) = self.get_vertex(k)? {
out.push(v);
}
}
Ok(out)
}
fn get_edge(&mut self, key: &EdgeKey) -> Result<Option<Edge>, StoreError>;
fn get_edges(&mut self, keys: &[EdgeKey]) -> Result<Vec<Edge>, StoreError> {
let mut out = Vec::with_capacity(keys.len());
for k in keys {
if let Some(e) = self.get_edge(k)? {
out.push(e);
}
}
Ok(out)
}
fn get_adjacent_edges(
&mut self,
vertex: VertexKey,
direction: Direction,
opts: AdjacentEdgesOptions<'_>,
limit: Option<u32>,
) -> Result<(Vec<Edge>, Option<AdjacentEdgeCursor>), StoreError>;
fn scan_vertices(
&mut self,
label: Option<LabelId>,
start_from: Option<VertexKey>,
limit: u32,
) -> Result<(Vec<Vertex>, Option<VertexKey>), StoreError>;
fn scan_edges(
&mut self,
label: Option<LabelId>,
start_from: Option<CanonicalEdgeKey>,
limit: u32,
) -> Result<(Vec<Edge>, Option<CanonicalEdgeKey>), StoreError>;
fn get_vertex_degree(&mut self, key: VertexKey) -> Result<Option<(u32, u32, LabelId)>, StoreError>;
}
pub trait GraphTransaction {
fn get_vertex(&mut self, key: VertexKey) -> Result<Option<Vertex>, StoreError>;
fn get_vertices(&mut self, keys: &[VertexKey]) -> Result<Vec<Vertex>, StoreError> {
let mut out = Vec::with_capacity(keys.len());
for &k in keys {
if let Some(v) = self.get_vertex(k)? {
out.push(v);
}
}
Ok(out)
}
fn get_vertex_degree(&mut self, key: VertexKey) -> Result<Option<(u32, u32, LabelId)>, StoreError>;
fn get_edge(&mut self, key: &EdgeKey) -> Result<Option<Edge>, StoreError>;
fn get_edges(&mut self, keys: &[EdgeKey]) -> Result<Vec<Edge>, StoreError> {
let mut out = Vec::with_capacity(keys.len());
for k in keys {
if let Some(e) = self.get_edge(k)? {
out.push(e);
}
}
Ok(out)
}
fn get_adjacent_edges(
&mut self,
vertex: VertexKey,
direction: Direction,
opts: AdjacentEdgesOptions<'_>,
limit: Option<u32>,
) -> Result<(Vec<Edge>, Option<AdjacentEdgeCursor>), StoreError>;
fn scan_vertices(
&mut self,
label: Option<LabelId>,
start_from: Option<VertexKey>,
limit: u32,
) -> Result<(Vec<Vertex>, Option<VertexKey>), StoreError>;
fn scan_edges(
&mut self,
label: Option<LabelId>,
start_from: Option<CanonicalEdgeKey>,
limit: u32,
) -> Result<(Vec<Edge>, Option<CanonicalEdgeKey>), StoreError>;
fn put_vertex(
&mut self,
key: VertexKey,
label_id: LabelId,
props: &HashMap<u16, Primitive>,
) -> Result<(), StoreError>;
fn put_vertex_degree(
&mut self,
key: VertexKey,
out_e_cnt: u32,
in_e_cnt: u32,
vertex_label_id: LabelId,
) -> Result<(), StoreError>;
fn put_edge(
&mut self,
key: &EdgeKey,
end_vertex_label: LabelId,
props: &HashMap<u16, Primitive>,
) -> Result<(), StoreError>;
fn delete_vertex(&mut self, key: VertexKey) -> Result<(), StoreError>;
fn delete_vertex_degree(&mut self, key: VertexKey) -> Result<(), StoreError>;
fn delete_edge(&mut self, key: &EdgeKey) -> Result<(), StoreError>;
fn put_schema_entry(&mut self, kind: u8, name: &str, value: &[u8]) -> Result<(), StoreError>;
fn commit(&mut self) -> Result<(), StoreError>;
fn abort(&mut self);
}
pub trait GraphStore {
type Snapshot: GraphSnapshot;
type Txn: GraphTransaction;
fn snapshot(&self) -> Self::Snapshot;
fn begin(&self) -> Self::Txn;
}
#[cfg(test)]
mod tests {
use super::*;
struct MockSnapshot;
impl GraphSnapshot for MockSnapshot {
fn get_vertex(&mut self, key: VertexKey) -> Result<Option<Vertex>, StoreError> {
if key == 999 {
return Err(StoreError::TraversalError("test vertex error".to_string()));
}
if key == 1 {
Ok(Some(Vertex::new(1, 2)))
} else {
Ok(None)
}
}
fn get_edge(&mut self, key: &EdgeKey) -> Result<Option<Edge>, StoreError> {
if key.primary_id == 999 {
return Err(StoreError::TraversalError("test edge error".to_string()));
}
if key.primary_id == 1 {
Ok(Some(Edge::new(1, 2, 3, 0, None, None)))
} else {
Ok(None)
}
}
fn get_adjacent_edges(
&mut self,
_vertex: VertexKey,
_direction: Direction,
_opts: AdjacentEdgesOptions<'_>,
_limit: Option<u32>,
) -> Result<(Vec<Edge>, Option<AdjacentEdgeCursor>), StoreError> {
Ok((vec![], None))
}
fn scan_vertices(
&mut self,
_label: Option<LabelId>,
_start_from: Option<VertexKey>,
_limit: u32,
) -> Result<(Vec<Vertex>, Option<VertexKey>), StoreError> {
Err(StoreError::UnsupportedOperation("MockSnapshot does not support scan_vertices".to_string()))
}
fn scan_edges(
&mut self,
_label: Option<LabelId>,
_start_from: Option<CanonicalEdgeKey>,
_limit: u32,
) -> Result<(Vec<Edge>, Option<CanonicalEdgeKey>), StoreError> {
Err(StoreError::UnsupportedOperation("MockSnapshot does not support scan_edges".to_string()))
}
fn get_vertex_degree(&mut self, _key: VertexKey) -> Result<Option<(u32, u32, LabelId)>, StoreError> {
Ok(None)
}
}
struct MockTxn;
impl GraphTransaction for MockTxn {
fn get_vertex(&mut self, key: VertexKey) -> Result<Option<Vertex>, StoreError> {
if key == 999 {
return Err(StoreError::TraversalError("test vertex error".to_string()));
}
if key == 1 {
Ok(Some(Vertex::new(1, 2)))
} else {
Ok(None)
}
}
fn get_vertex_degree(&mut self, _key: VertexKey) -> Result<Option<(u32, u32, LabelId)>, StoreError> {
Ok(None)
}
fn get_edge(&mut self, key: &EdgeKey) -> Result<Option<Edge>, StoreError> {
if key.primary_id == 999 {
return Err(StoreError::TraversalError("test edge error".to_string()));
}
if key.primary_id == 1 {
Ok(Some(Edge::new(1, 2, 3, 0, None, None)))
} else {
Ok(None)
}
}
fn get_adjacent_edges(
&mut self,
_vertex: VertexKey,
_direction: Direction,
_opts: AdjacentEdgesOptions<'_>,
_limit: Option<u32>,
) -> Result<(Vec<Edge>, Option<AdjacentEdgeCursor>), StoreError> {
Ok((vec![], None))
}
fn scan_vertices(
&mut self,
_label: Option<LabelId>,
_start_from: Option<VertexKey>,
_limit: u32,
) -> Result<(Vec<Vertex>, Option<VertexKey>), StoreError> {
Err(StoreError::UnsupportedOperation("MockTxn does not support scan_vertices".to_string()))
}
fn scan_edges(
&mut self,
_label: Option<LabelId>,
_start_from: Option<CanonicalEdgeKey>,
_limit: u32,
) -> Result<(Vec<Edge>, Option<CanonicalEdgeKey>), StoreError> {
Err(StoreError::UnsupportedOperation("MockTxn does not support scan_edges".to_string()))
}
fn put_vertex(
&mut self,
_key: VertexKey,
_label_id: LabelId,
_props: &HashMap<u16, Primitive>,
) -> Result<(), StoreError> {
Ok(())
}
fn put_vertex_degree(
&mut self,
_key: VertexKey,
_out_e_cnt: u32,
_in_e_cnt: u32,
_vertex_label_id: LabelId,
) -> Result<(), StoreError> {
Ok(())
}
fn put_edge(
&mut self,
_key: &EdgeKey,
_end_vertex_label: LabelId,
_props: &HashMap<u16, Primitive>,
) -> Result<(), StoreError> {
Ok(())
}
fn delete_vertex(&mut self, _key: VertexKey) -> Result<(), StoreError> {
Ok(())
}
fn delete_vertex_degree(&mut self, _key: VertexKey) -> Result<(), StoreError> {
Ok(())
}
fn delete_edge(&mut self, _key: &EdgeKey) -> Result<(), StoreError> {
Ok(())
}
fn put_schema_entry(&mut self, _kind: u8, _name: &str, _value: &[u8]) -> Result<(), StoreError> {
Ok(())
}
fn commit(&mut self) -> Result<(), StoreError> {
Ok(())
}
fn abort(&mut self) {}
}
struct MockStore;
impl GraphStore for MockStore {
type Snapshot = MockSnapshot;
type Txn = MockTxn;
fn snapshot(&self) -> Self::Snapshot {
MockSnapshot
}
fn begin(&self) -> Self::Txn {
MockTxn
}
}
#[test]
fn test_traits_default_methods() {
let mut snap = MockSnapshot;
let vs = snap.get_vertices(&[1, 2]).unwrap();
assert_eq!(vs.len(), 1);
assert_eq!(vs[0].id, 1);
assert!(snap.get_vertices(&[999]).is_err());
let ek1 = EdgeKey { primary_id: 1, direction: Direction::OUT, label_id: 2, secondary_id: 3, rank: 0 };
let ek2 = EdgeKey { primary_id: 42, direction: Direction::OUT, label_id: 2, secondary_id: 3, rank: 0 };
let ek_err = EdgeKey { primary_id: 999, direction: Direction::OUT, label_id: 2, secondary_id: 3, rank: 0 };
let es = snap.get_edges(&[ek1, ek2]).unwrap();
assert_eq!(es.len(), 1);
assert_eq!(es[0].src_id, 1);
assert!(snap.get_edges(&[ek_err]).is_err());
assert!(snap.scan_vertices(None, None, 10).is_err());
assert!(snap.scan_edges(None, None, 10).is_err());
let mut txn = MockTxn;
let vs_txn = txn.get_vertices(&[1, 2]).unwrap();
assert_eq!(vs_txn.len(), 1);
assert!(txn.get_vertices(&[999]).is_err());
let es_txn = txn.get_edges(&[ek1, ek2]).unwrap();
assert_eq!(es_txn.len(), 1);
assert!(txn.get_edges(&[ek_err]).is_err());
assert!(txn.scan_vertices(None, None, 10).is_err());
assert!(txn.scan_edges(None, None, 10).is_err());
let store = MockStore;
let mut s_snap = store.snapshot();
assert!(s_snap.get_vertex(1).is_ok());
let mut s_txn = store.begin();
assert!(s_txn.get_vertex(1).is_ok());
assert!(snap
.get_adjacent_edges(
1,
Direction::OUT,
AdjacentEdgesOptions { label: None, dst: None, rank: None, start_from: None },
None
)
.is_ok());
assert!(txn
.get_adjacent_edges(
1,
Direction::OUT,
AdjacentEdgesOptions { label: None, dst: None, rank: None, start_from: None },
None
)
.is_ok());
assert!(txn.get_vertex_degree(1).is_ok());
assert!(txn.put_vertex(1, 1, &HashMap::new()).is_ok());
assert!(txn.put_vertex_degree(1, 0, 0, 0).is_ok());
assert!(txn.put_edge(&ek1, 0, &HashMap::new()).is_ok());
assert!(txn.delete_vertex(1).is_ok());
assert!(txn.delete_vertex_degree(1).is_ok());
assert!(txn.delete_edge(&ek1).is_ok());
assert!(txn.put_schema_entry(0, "name", &[]).is_ok());
assert!(txn.commit().is_ok());
txn.abort();
}
}