pub mod membership;
use cypherlite_core::{PropertyValue, SubgraphId, SubgraphRecord};
use std::collections::BTreeMap;
pub struct SubgraphStore {
records: BTreeMap<u64, SubgraphRecord>,
next_id: u64,
}
impl SubgraphStore {
pub fn new(start_id: u64) -> Self {
Self {
records: BTreeMap::new(),
next_id: start_id,
}
}
pub fn create(
&mut self,
properties: Vec<(u32, PropertyValue)>,
temporal_anchor: Option<i64>,
) -> SubgraphId {
let id = SubgraphId(self.next_id);
let record = SubgraphRecord {
subgraph_id: id,
temporal_anchor,
properties,
};
self.records.insert(self.next_id, record);
self.next_id += 1;
id
}
pub fn get(&self, id: SubgraphId) -> Option<&SubgraphRecord> {
self.records.get(&id.0)
}
pub fn delete(&mut self, id: SubgraphId) -> Option<SubgraphRecord> {
self.records.remove(&id.0)
}
pub fn next_id(&self) -> u64 {
self.next_id
}
pub fn len(&self) -> usize {
self.records.len()
}
pub fn is_empty(&self) -> bool {
self.records.is_empty()
}
pub fn all(&self) -> impl Iterator<Item = &SubgraphRecord> {
self.records.values()
}
pub fn insert_loaded_record(&mut self, record: SubgraphRecord) {
let id = record.subgraph_id.0;
self.records.insert(id, record);
if id >= self.next_id {
self.next_id = id + 1;
}
}
}
impl Default for SubgraphStore {
fn default() -> Self {
Self::new(1)
}
}
#[cfg(test)]
mod tests {
use cypherlite_core::{PropertyValue, SubgraphId};
use super::*;
#[test]
fn test_subgraph_store_new_is_empty() {
let store = SubgraphStore::new(1);
assert_eq!(store.len(), 0);
}
#[test]
fn test_create_subgraph() {
let mut store = SubgraphStore::new(1);
let id = store.create(vec![], None);
assert_eq!(id, SubgraphId(1));
assert_eq!(store.len(), 1);
}
#[test]
fn test_create_subgraph_with_properties() {
let mut store = SubgraphStore::new(1);
let props = vec![(1, PropertyValue::String("my-graph".into()))];
let id = store.create(props.clone(), Some(1_700_000_000_000));
let record = store.get(id).expect("found");
assert_eq!(record.subgraph_id, id);
assert_eq!(record.temporal_anchor, Some(1_700_000_000_000));
assert_eq!(record.properties, props);
}
#[test]
fn test_create_multiple_subgraphs() {
let mut store = SubgraphStore::new(1);
let id1 = store.create(vec![], None);
let id2 = store.create(vec![], None);
let id3 = store.create(vec![], None);
assert_eq!(id1, SubgraphId(1));
assert_eq!(id2, SubgraphId(2));
assert_eq!(id3, SubgraphId(3));
assert_eq!(store.len(), 3);
}
#[test]
fn test_get_subgraph() {
let mut store = SubgraphStore::new(1);
let id = store.create(vec![(1, PropertyValue::Int64(42))], None);
let record = store.get(id).expect("found");
assert_eq!(record.subgraph_id, id);
assert_eq!(record.properties.len(), 1);
}
#[test]
fn test_get_nonexistent_subgraph() {
let store = SubgraphStore::new(1);
assert!(store.get(SubgraphId(999)).is_none());
}
#[test]
fn test_delete_subgraph() {
let mut store = SubgraphStore::new(1);
let id = store.create(vec![], None);
let deleted = store.delete(id);
assert!(deleted.is_some());
assert!(store.get(id).is_none());
assert_eq!(store.len(), 0);
}
#[test]
fn test_delete_nonexistent_subgraph() {
let mut store = SubgraphStore::new(1);
assert!(store.delete(SubgraphId(999)).is_none());
}
#[test]
fn test_next_id() {
let mut store = SubgraphStore::new(1);
assert_eq!(store.next_id(), 1);
store.create(vec![], None);
assert_eq!(store.next_id(), 2);
}
#[test]
fn test_subgraph_store_default() {
let store = SubgraphStore::default();
assert_eq!(store.len(), 0);
assert_eq!(store.next_id(), 1);
}
}