simple-triplestore 0.1.1

A simple graph database for storing triples with support for custom node and edge properties.
Documentation
use crate::{
    prelude::*,
    traits::{IdType, Property},
    Query, QueryError, Triple,
};

use super::MemTripleStore;

impl<Id: IdType, NodeProps: Property, EdgeProps: Property>
    TripleStoreQuery<Id, NodeProps, EdgeProps> for MemTripleStore<Id, NodeProps, EdgeProps>
{
    type QueryResult = MemTripleStore<Id, NodeProps, EdgeProps>;
    type QueryResultError = ();

    fn run(
        &self,
        query: Query<Id>,
    ) -> Result<
        MemTripleStore<Id, NodeProps, EdgeProps>,
        QueryError<Self::Error, Self::QueryResultError>,
    > {
        Ok(match query {
            Query::NodeProps(nodes) => {
                let mut result =
                    MemTripleStore::new_from_boxed_id_generator(self.id_generator.clone());
                for node in nodes {
                    if let Some(data) = self.node_props.get(&node) {
                        result.node_props.insert(node, data.clone());
                    }
                }
                result
            }

            Query::SPO(triples) => {
                let mut result =
                    MemTripleStore::new_from_boxed_id_generator(self.id_generator.clone());
                for (sub, pred, obj) in triples.into_iter() {
                    let triple = Triple { sub, pred, obj };
                    if let Some(data_id) = self.spo_data.get(&Id::encode_spo_triple(&triple)) {
                        if let Some(data) = self.edge_props.get(&data_id) {
                            result
                                .insert_edge(triple, data.clone())
                                .map_err(|e| QueryError::Right(e))?;
                        }
                    }
                }
                result
            }

            Query::S(items) => {
                let mut result =
                    MemTripleStore::new_from_boxed_id_generator(self.id_generator.clone());
                for sub in items {
                    for (key, data_id) in self.spo_data.range(Id::key_bounds_1(sub)) {
                        if let Some(data) = self.edge_props.get(&data_id) {
                            result
                                .insert_edge(Id::decode_spo_triple(&key), data.clone())
                                .map_err(|e| QueryError::Right(e))?;
                        }
                    }
                }
                result
            }

            Query::SP(items) => {
                let mut result =
                    MemTripleStore::new_from_boxed_id_generator(self.id_generator.clone());
                for (sub, pred) in items {
                    for (key, data_id) in self.spo_data.range(Id::key_bounds_2(sub, pred)) {
                        if let Some(data) = self.edge_props.get(&data_id) {
                            result
                                .insert_edge(Id::decode_spo_triple(&key), data.clone())
                                .map_err(|e| QueryError::Right(e))?;
                        }
                    }
                }
                result
            }

            Query::SO(items) => {
                let mut result =
                    MemTripleStore::new_from_boxed_id_generator(self.id_generator.clone());
                for (sub, obj) in items {
                    for (key, data_id) in self.osp_data.range(Id::key_bounds_2(obj, sub)) {
                        if let Some(data) = self.edge_props.get(&data_id) {
                            result
                                .insert_edge(Id::decode_osp_triple(key), data.clone())
                                .map_err(|e| QueryError::Right(e))?;
                        }
                    }
                }
                result
            }

            Query::P(items) => {
                let mut result =
                    MemTripleStore::new_from_boxed_id_generator(self.id_generator.clone());
                for pred in items {
                    for (key, data_id) in self.pos_data.range(Id::key_bounds_1(pred)) {
                        if let Some(data) = self.edge_props.get(&data_id) {
                            result
                                .insert_edge(Id::decode_pos_triple(key), data.clone())
                                .map_err(|e| QueryError::Right(e))?;
                        }
                    }
                }
                result
            }

            Query::PO(items) => {
                let mut result =
                    MemTripleStore::new_from_boxed_id_generator(self.id_generator.clone());
                for (pred, obj) in items {
                    for (key, data_id) in self.pos_data.range(Id::key_bounds_2(pred, obj)) {
                        if let Some(data) = self.edge_props.get(&data_id) {
                            result
                                .insert_edge(Id::decode_pos_triple(key), data.clone())
                                .map_err(|e| QueryError::Right(e))?;
                        }
                    }
                }
                result
            }

            Query::O(items) => {
                let mut result =
                    MemTripleStore::new_from_boxed_id_generator(self.id_generator.clone());
                for obj in items {
                    for (key, data_id) in self.osp_data.range(Id::key_bounds_1(obj)) {
                        if let Some(data) = self.edge_props.get(&data_id) {
                            result
                                .insert_edge(Id::decode_osp_triple(key), data.clone())
                                .map_err(|e| QueryError::Right(e))?;
                        }
                    }
                }
                result
            }
        })
    }
}

#[cfg(test)]
mod test {
    use crate::{MemTripleStore, UlidIdGenerator};

    #[test]
    fn test_query_node_props() {
        crate::conformance::query::test_query_node_props(MemTripleStore::new(
            UlidIdGenerator::new(),
        ));
    }

    #[test]
    fn test_query_edge_props() {
        crate::conformance::query::test_query_edge_props(MemTripleStore::new(
            UlidIdGenerator::new(),
        ));
    }

    #[test]
    fn test_query_s() {
        crate::conformance::query::test_query_s(MemTripleStore::new(UlidIdGenerator::new()));
    }

    #[test]
    fn test_query_sp() {
        crate::conformance::query::test_query_sp(MemTripleStore::new(UlidIdGenerator::new()));
    }

    #[test]
    fn test_query_p() {
        crate::conformance::query::test_query_p(MemTripleStore::new(UlidIdGenerator::new()));
    }

    #[test]
    fn test_query_po() {
        crate::conformance::query::test_query_po(MemTripleStore::new(UlidIdGenerator::new()));
    }

    #[test]
    fn test_query_o() {
        crate::conformance::query::test_query_o(MemTripleStore::new(UlidIdGenerator::new()));
    }

    #[test]
    fn test_query_os() {
        crate::conformance::query::test_query_os(MemTripleStore::new(UlidIdGenerator::new()));
    }
}