use oxrdf::{NamedNode, Quad, Term};
use vertep_store::{GraphStore, JournalStore, MemoryStore, Solutions, StoreError};
pub trait Storage: Send + Sync {
fn journal(&self) -> &dyn JournalStore;
fn graph(&self, actor: &NamedNode) -> &dyn GraphStore;
fn graphs(&self) -> Vec<&dyn GraphStore>;
}
impl<S: Storage + ?Sized> Storage for std::sync::Arc<S> {
fn journal(&self) -> &dyn JournalStore {
(**self).journal()
}
fn graph(&self, actor: &NamedNode) -> &dyn GraphStore {
(**self).graph(actor)
}
fn graphs(&self) -> Vec<&dyn GraphStore> {
(**self).graphs()
}
}
impl Storage for MemoryStore {
fn journal(&self) -> &dyn JournalStore {
self
}
fn graph(&self, _actor: &NamedNode) -> &dyn GraphStore {
self
}
fn graphs(&self) -> Vec<&dyn GraphStore> {
vec![self]
}
}
#[cfg(feature = "tiramemsu")]
impl Storage for vertep_tiramemsu::TiramemsuShard {
fn journal(&self) -> &dyn JournalStore {
self
}
fn graph(&self, _actor: &NamedNode) -> &dyn GraphStore {
self
}
fn graphs(&self) -> Vec<&dyn GraphStore> {
vec![self]
}
}
#[cfg(feature = "tiramemsu")]
impl Storage for vertep_tiramemsu::TiramemsuBackend {
fn journal(&self) -> &dyn JournalStore {
self
}
fn graph(&self, actor: &NamedNode) -> &dyn GraphStore {
self.shard_for(actor)
}
fn graphs(&self) -> Vec<&dyn GraphStore> {
self.shards().iter().map(|s| s as &dyn GraphStore).collect()
}
}
pub struct SplitStorage<J, G> {
pub journal: J,
pub graph: G,
}
impl<J, G> std::fmt::Debug for SplitStorage<J, G> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SplitStorage").finish_non_exhaustive()
}
}
impl<J: JournalStore, G: GraphStore> Storage for SplitStorage<J, G> {
fn journal(&self) -> &dyn JournalStore {
&self.journal
}
fn graph(&self, _actor: &NamedNode) -> &dyn GraphStore {
&self.graph
}
fn graphs(&self) -> Vec<&dyn GraphStore> {
vec![&self.graph]
}
}
pub(crate) fn select(g: &dyn GraphStore, sparql: &str) -> Result<Solutions, StoreError> {
g.query(sparql)?.into_solutions()
}
pub(crate) fn text(t: &Term) -> Option<String> {
match t {
Term::Literal(l) => Some(l.value().to_owned()),
Term::NamedNode(n) => Some(n.as_str().to_owned()),
_ => None,
}
}
pub(crate) fn graph_quads(g: &dyn GraphStore, graph: &NamedNode) -> Result<Vec<Quad>, StoreError> {
let q = format!("SELECT ?s ?p ?o WHERE {{ GRAPH {graph} {{ ?s ?p ?o }} }}");
let sol = select(g, &q)?;
let mut out = Vec::new();
for i in 0..sol.len() {
let (Some(s), Some(p), Some(o)) = (sol.get(i, "s"), sol.get(i, "p"), sol.get(i, "o"))
else {
continue;
};
let s = match s {
Term::NamedNode(n) => oxrdf::NamedOrBlankNode::from(n.clone()),
Term::BlankNode(b) => oxrdf::NamedOrBlankNode::from(b.clone()),
_ => continue,
};
let Term::NamedNode(p) = p else { continue };
out.push(Quad::new(s, p.clone(), o.clone(), graph.clone()));
}
Ok(out)
}