Simplifies Sophia traits implementation

pull/171/head
Tpt 4 years ago
parent 943d116f56
commit 13ee6bf80c
  1. 877
      lib/src/store/sophia.rs

@ -1,364 +1,330 @@
//! This crate provides implementation of [Sophia](https://docs.rs/sophia/) traits for the `store` module. //! This crate provides implementation of [Sophia](https://docs.rs/sophia/) traits for the `store` module.
use crate::model::*;
use crate::model::{
BlankNodeRef, GraphNameRef, LiteralRef, NamedNodeRef, NamedOrBlankNodeRef, Quad, QuadRef, Term,
TermRef,
};
use crate::sparql::{EvaluationError, QueryResults}; use crate::sparql::{EvaluationError, QueryResults};
use crate::store::*; use crate::store::SledStore;
use sophia_api::dataset::*; use sophia_api::dataset::{
CollectibleDataset, DQuadSource, DResultTermSet, DTerm, Dataset, MDResult, MutableDataset,
};
use sophia_api::quad::stream::{QuadSource, StreamResult}; use sophia_api::quad::stream::{QuadSource, StreamResult};
use sophia_api::quad::streaming_mode::{ByValue, StreamedQuad}; use sophia_api::quad::streaming_mode::{ByValue, StreamedQuad};
use sophia_api::term::{TTerm, TermKind}; use sophia_api::term::{TTerm, TermKind};
use std::collections::HashSet; use std::collections::HashSet;
use std::hash::Hash; use std::hash::Hash;
use std::io::{Error, ErrorKind};
use std::iter::empty; use std::iter::empty;
type SophiaQuad = ([Term; 3], Option<Term>); type SophiaQuad = ([Term; 3], Option<Term>);
type StreamedSophiaQuad<'a> = StreamedQuad<'a, ByValue<SophiaQuad>>; type StreamedSophiaQuad<'a> = StreamedQuad<'a, ByValue<SophiaQuad>>;
/// Execute a SPARQL query in a store, and return the result as a HashSet, impl Dataset for SledStore {
/// mapping the error (if any) through the given function. type Quad = ByValue<SophiaQuad>;
/// type Error = Error;
/// # Precondition
/// + the query must be a SELECT query with a single selected variable
/// + it must not produce NULL results
macro_rules! sparql_to_hashset {
($store: ident, $err_map: ident, $sparql: expr) => {{
(|| -> Result<HashSet<Term>, EvaluationError> {
if let QueryResults::Solutions(solutions) = $store.query($sparql)? {
solutions
.map(|r| r.map(|v| v.get(0).unwrap().clone()))
.collect()
} else {
unreachable!()
}
})()
.map_err($err_map)
}};
}
macro_rules! impl_dataset { fn quads(&self) -> DQuadSource<'_, Self> {
($store: ident, $error: ty, $quad_map: ident, $err_map: ident) => { Box::new(self.iter().map(io_quad_map))
impl Dataset for $store { }
type Quad = ByValue<SophiaQuad>;
type Error = $error;
fn quads(&self) -> DQuadSource<'_, Self> { fn quads_with_s<'s, TS>(&'s self, s: &'s TS) -> DQuadSource<'s, Self>
Box::new( where
self.quads_for_pattern(None, None, None, None) TS: TTerm + ?Sized,
.map($quad_map), {
) let mut buf_s = String::new();
} let s = convert_subject(s, &mut buf_s);
fn quads_with_s<'s, TS>(&'s self, s: &'s TS) -> DQuadSource<'s, Self> if s.is_none() {
where Box::new(empty())
TS: TTerm + ?Sized, } else {
{ Box::new(self.quads_for_pattern(s, None, None, None).map(io_quad_map))
let mut buf_s = String::new(); }
let s = convert_subject(s, &mut buf_s); }
if s.is_none() { fn quads_with_p<'s, TP>(&'s self, p: &'s TP) -> DQuadSource<'s, Self>
Box::new(empty()) where
} else { TP: TTerm + ?Sized,
Box::new(self.quads_for_pattern(s, None, None, None).map($quad_map)) {
} let mut buf_p = String::new();
} let p = convert_predicate(p, &mut buf_p);
fn quads_with_p<'s, TP>(&'s self, p: &'s TP) -> DQuadSource<'s, Self> if p.is_none() {
where Box::new(empty())
TP: TTerm + ?Sized, } else {
{ Box::new(self.quads_for_pattern(None, p, None, None).map(io_quad_map))
let mut buf_p = String::new(); }
let p = convert_predicate(p, &mut buf_p); }
if p.is_none() { fn quads_with_o<'s, TS>(&'s self, o: &'s TS) -> DQuadSource<'s, Self>
Box::new(empty()) where
} else { TS: TTerm + ?Sized,
Box::new(self.quads_for_pattern(None, p, None, None).map($quad_map)) {
} let mut buf_o = String::new();
} let o = convert_object(o, &mut buf_o);
fn quads_with_o<'s, TS>(&'s self, o: &'s TS) -> DQuadSource<'s, Self> if o.is_none() {
where Box::new(empty())
TS: TTerm + ?Sized, } else {
{ Box::new(self.quads_for_pattern(None, None, o, None).map(io_quad_map))
let mut buf_o = String::new(); }
let o = convert_object(o, &mut buf_o); }
if o.is_none() { fn quads_with_g<'s, TS>(&'s self, g: Option<&'s TS>) -> DQuadSource<'s, Self>
Box::new(empty()) where
} else { TS: TTerm + ?Sized,
Box::new(self.quads_for_pattern(None, None, o, None).map($quad_map)) {
} let mut buf_g = String::new();
} let g = convert_graph_name(g, &mut buf_g);
fn quads_with_g<'s, TS>(&'s self, g: Option<&'s TS>) -> DQuadSource<'s, Self> if g.is_none() {
where Box::new(empty())
TS: TTerm + ?Sized, } else {
{ Box::new(self.quads_for_pattern(None, None, None, g).map(io_quad_map))
let mut buf_g = String::new(); }
let g = convert_graph_name(g, &mut buf_g); }
if g.is_none() { fn quads_with_sp<'s, TS, TP>(&'s self, s: &'s TS, p: &'s TP) -> DQuadSource<'s, Self>
Box::new(empty()) where
} else { TS: TTerm + ?Sized,
Box::new(self.quads_for_pattern(None, None, None, g).map($quad_map)) TP: TTerm + ?Sized,
} {
} let mut buf_s = String::new();
fn quads_with_sp<'s, TS, TP>(&'s self, s: &'s TS, p: &'s TP) -> DQuadSource<'s, Self> let s = convert_subject(s, &mut buf_s);
where let mut buf_p = String::new();
TS: TTerm + ?Sized, let p = convert_predicate(p, &mut buf_p);
TP: TTerm + ?Sized, if s.is_none() || p.is_none() {
{ Box::new(empty())
let mut buf_s = String::new(); } else {
let s = convert_subject(s, &mut buf_s); Box::new(self.quads_for_pattern(s, p, None, None).map(io_quad_map))
let mut buf_p = String::new(); }
let p = convert_predicate(p, &mut buf_p); }
if s.is_none() || p.is_none() { fn quads_with_so<'s, TS, TO>(&'s self, s: &'s TS, o: &'s TO) -> DQuadSource<'s, Self>
Box::new(empty()) where
} else { TS: TTerm + ?Sized,
Box::new(self.quads_for_pattern(s, p, None, None).map($quad_map)) TO: TTerm + ?Sized,
} {
} let mut buf_s = String::new();
fn quads_with_so<'s, TS, TO>(&'s self, s: &'s TS, o: &'s TO) -> DQuadSource<'s, Self> let s = convert_subject(s, &mut buf_s);
where let mut buf_o = String::new();
TS: TTerm + ?Sized, let o = convert_object(o, &mut buf_o);
TO: TTerm + ?Sized, if s.is_none() || o.is_none() {
{ Box::new(empty())
let mut buf_s = String::new(); } else {
let s = convert_subject(s, &mut buf_s); Box::new(self.quads_for_pattern(s, None, o, None).map(io_quad_map))
let mut buf_o = String::new(); }
let o = convert_object(o, &mut buf_o); }
if s.is_none() || o.is_none() { fn quads_with_sg<'s, TS, TG>(&'s self, s: &'s TS, g: Option<&'s TG>) -> DQuadSource<'s, Self>
Box::new(empty()) where
} else { TS: TTerm + ?Sized,
Box::new(self.quads_for_pattern(s, None, o, None).map($quad_map)) TG: TTerm + ?Sized,
} {
} let mut buf_s = String::new();
fn quads_with_sg<'s, TS, TG>( let s = convert_subject(s, &mut buf_s);
&'s self, let mut buf_g = String::new();
s: &'s TS, let g = convert_graph_name(g, &mut buf_g);
g: Option<&'s TG>, if s.is_none() || g.is_none() {
) -> DQuadSource<'s, Self> Box::new(empty())
where } else {
TS: TTerm + ?Sized, Box::new(self.quads_for_pattern(s, None, None, g).map(io_quad_map))
TG: TTerm + ?Sized, }
{ }
let mut buf_s = String::new(); fn quads_with_po<'s, TP, TO>(&'s self, p: &'s TP, o: &'s TO) -> DQuadSource<'s, Self>
let s = convert_subject(s, &mut buf_s); where
let mut buf_g = String::new(); TP: TTerm + ?Sized,
let g = convert_graph_name(g, &mut buf_g); TO: TTerm + ?Sized,
if s.is_none() || g.is_none() { {
Box::new(empty()) let mut buf_p = String::new();
} else { let p = convert_predicate(p, &mut buf_p);
Box::new(self.quads_for_pattern(s, None, None, g).map($quad_map)) let mut buf_o = String::new();
} let o = convert_object(o, &mut buf_o);
} if p.is_none() || o.is_none() {
fn quads_with_po<'s, TP, TO>(&'s self, p: &'s TP, o: &'s TO) -> DQuadSource<'s, Self> Box::new(empty())
where } else {
TP: TTerm + ?Sized, Box::new(self.quads_for_pattern(None, p, o, None).map(io_quad_map))
TO: TTerm + ?Sized, }
{ }
let mut buf_p = String::new(); fn quads_with_pg<'s, TP, TG>(&'s self, p: &'s TP, g: Option<&'s TG>) -> DQuadSource<'s, Self>
let p = convert_predicate(p, &mut buf_p); where
let mut buf_o = String::new(); TP: TTerm + ?Sized,
let o = convert_object(o, &mut buf_o); TG: TTerm + ?Sized,
if p.is_none() || o.is_none() { {
Box::new(empty()) let mut buf_p = String::new();
} else { let p = convert_predicate(p, &mut buf_p);
Box::new(self.quads_for_pattern(None, p, o, None).map($quad_map)) let mut buf_g = String::new();
} let g = convert_graph_name(g, &mut buf_g);
} if p.is_none() || g.is_none() {
fn quads_with_pg<'s, TP, TG>( Box::new(empty())
&'s self, } else {
p: &'s TP, Box::new(self.quads_for_pattern(None, p, None, g).map(io_quad_map))
g: Option<&'s TG>, }
) -> DQuadSource<'s, Self> }
where fn quads_with_og<'s, TO, TG>(&'s self, o: &'s TO, g: Option<&'s TG>) -> DQuadSource<'s, Self>
TP: TTerm + ?Sized, where
TG: TTerm + ?Sized, TO: TTerm + ?Sized,
{ TG: TTerm + ?Sized,
let mut buf_p = String::new(); {
let p = convert_predicate(p, &mut buf_p); let mut buf_o = String::new();
let mut buf_g = String::new(); let o = convert_object(o, &mut buf_o);
let g = convert_graph_name(g, &mut buf_g); let mut buf_g = String::new();
if p.is_none() || g.is_none() { let g = convert_graph_name(g, &mut buf_g);
Box::new(empty()) if o.is_none() || g.is_none() {
} else { Box::new(empty())
Box::new(self.quads_for_pattern(None, p, None, g).map($quad_map)) } else {
} Box::new(self.quads_for_pattern(None, None, o, g).map(io_quad_map))
} }
fn quads_with_og<'s, TO, TG>( }
&'s self, fn quads_with_spo<'s, TS, TP, TO>(
o: &'s TO, &'s self,
g: Option<&'s TG>, s: &'s TS,
) -> DQuadSource<'s, Self> p: &'s TP,
where o: &'s TO,
TO: TTerm + ?Sized, ) -> DQuadSource<'s, Self>
TG: TTerm + ?Sized, where
{ TS: TTerm + ?Sized,
let mut buf_o = String::new(); TP: TTerm + ?Sized,
let o = convert_object(o, &mut buf_o); TO: TTerm + ?Sized,
let mut buf_g = String::new(); {
let g = convert_graph_name(g, &mut buf_g); let mut buf_s = String::new();
if o.is_none() || g.is_none() { let s = convert_subject(s, &mut buf_s);
Box::new(empty()) let mut buf_p = String::new();
} else { let p = convert_predicate(p, &mut buf_p);
Box::new(self.quads_for_pattern(None, None, o, g).map($quad_map)) let mut buf_o = String::new();
} let o = convert_object(o, &mut buf_o);
} if s.is_none() || p.is_none() || o.is_none() {
fn quads_with_spo<'s, TS, TP, TO>( Box::new(empty())
&'s self, } else {
s: &'s TS, Box::new(self.quads_for_pattern(s, p, o, None).map(io_quad_map))
p: &'s TP, }
o: &'s TO, }
) -> DQuadSource<'s, Self> fn quads_with_spg<'s, TS, TP, TG>(
where &'s self,
TS: TTerm + ?Sized, s: &'s TS,
TP: TTerm + ?Sized, p: &'s TP,
TO: TTerm + ?Sized, g: Option<&'s TG>,
{ ) -> DQuadSource<'s, Self>
let mut buf_s = String::new(); where
let s = convert_subject(s, &mut buf_s); TS: TTerm + ?Sized,
let mut buf_p = String::new(); TP: TTerm + ?Sized,
let p = convert_predicate(p, &mut buf_p); TG: TTerm + ?Sized,
let mut buf_o = String::new(); {
let o = convert_object(o, &mut buf_o); let mut buf_s = String::new();
if s.is_none() || p.is_none() || o.is_none() { let s = convert_subject(s, &mut buf_s);
Box::new(empty()) let mut buf_p = String::new();
} else { let p = convert_predicate(p, &mut buf_p);
Box::new(self.quads_for_pattern(s, p, o, None).map($quad_map)) let mut buf_g = String::new();
} let g = convert_graph_name(g, &mut buf_g);
} if s.is_none() || p.is_none() || g.is_none() {
fn quads_with_spg<'s, TS, TP, TG>( Box::new(empty())
&'s self, } else {
s: &'s TS, Box::new(self.quads_for_pattern(s, p, None, g).map(io_quad_map))
p: &'s TP, }
g: Option<&'s TG>, }
) -> DQuadSource<'s, Self> fn quads_with_sog<'s, TS, TO, TG>(
where &'s self,
TS: TTerm + ?Sized, s: &'s TS,
TP: TTerm + ?Sized, o: &'s TO,
TG: TTerm + ?Sized, g: Option<&'s TG>,
{ ) -> DQuadSource<'s, Self>
let mut buf_s = String::new(); where
let s = convert_subject(s, &mut buf_s); TS: TTerm + ?Sized,
let mut buf_p = String::new(); TO: TTerm + ?Sized,
let p = convert_predicate(p, &mut buf_p); TG: TTerm + ?Sized,
let mut buf_g = String::new(); {
let g = convert_graph_name(g, &mut buf_g); let mut buf_s = String::new();
if s.is_none() || p.is_none() || g.is_none() { let s = convert_subject(s, &mut buf_s);
Box::new(empty()) let mut buf_o = String::new();
} else { let o = convert_object(o, &mut buf_o);
Box::new(self.quads_for_pattern(s, p, None, g).map($quad_map)) let mut buf_g = String::new();
} let g = convert_graph_name(g, &mut buf_g);
} if s.is_none() || o.is_none() || g.is_none() {
fn quads_with_sog<'s, TS, TO, TG>( Box::new(empty())
&'s self, } else {
s: &'s TS, Box::new(self.quads_for_pattern(s, None, o, g).map(io_quad_map))
o: &'s TO, }
g: Option<&'s TG>, }
) -> DQuadSource<'s, Self> fn quads_with_pog<'s, TP, TO, TG>(
where &'s self,
TS: TTerm + ?Sized, p: &'s TP,
TO: TTerm + ?Sized, o: &'s TO,
TG: TTerm + ?Sized, g: Option<&'s TG>,
{ ) -> DQuadSource<'s, Self>
let mut buf_s = String::new(); where
let s = convert_subject(s, &mut buf_s); TP: TTerm + ?Sized,
let mut buf_o = String::new(); TO: TTerm + ?Sized,
let o = convert_object(o, &mut buf_o); TG: TTerm + ?Sized,
let mut buf_g = String::new(); {
let g = convert_graph_name(g, &mut buf_g); let mut buf_p = String::new();
if s.is_none() || o.is_none() || g.is_none() { let p = convert_predicate(p, &mut buf_p);
Box::new(empty()) let mut buf_o = String::new();
} else { let o = convert_object(o, &mut buf_o);
Box::new(self.quads_for_pattern(s, None, o, g).map($quad_map)) let mut buf_g = String::new();
} let g = convert_graph_name(g, &mut buf_g);
} if p.is_none() || o.is_none() || g.is_none() {
fn quads_with_pog<'s, TP, TO, TG>( Box::new(empty())
&'s self, } else {
p: &'s TP, Box::new(self.quads_for_pattern(None, p, o, g).map(io_quad_map))
o: &'s TO, }
g: Option<&'s TG>, }
) -> DQuadSource<'s, Self> fn quads_with_spog<'s, TS, TP, TO, TG>(
where &'s self,
TP: TTerm + ?Sized, s: &'s TS,
TO: TTerm + ?Sized, p: &'s TP,
TG: TTerm + ?Sized, o: &'s TO,
{ g: Option<&'s TG>,
let mut buf_p = String::new(); ) -> DQuadSource<'s, Self>
let p = convert_predicate(p, &mut buf_p); where
let mut buf_o = String::new(); TS: TTerm + ?Sized,
let o = convert_object(o, &mut buf_o); TP: TTerm + ?Sized,
let mut buf_g = String::new(); TO: TTerm + ?Sized,
let g = convert_graph_name(g, &mut buf_g); TG: TTerm + ?Sized,
if p.is_none() || o.is_none() || g.is_none() { {
Box::new(empty()) let mut buf_s = String::new();
} else { let s = convert_subject(s, &mut buf_s);
Box::new(self.quads_for_pattern(None, p, o, g).map($quad_map)) let mut buf_p = String::new();
} let p = convert_predicate(p, &mut buf_p);
} let mut buf_o = String::new();
fn quads_with_spog<'s, TS, TP, TO, TG>( let o = convert_object(o, &mut buf_o);
&'s self, let mut buf_g = String::new();
s: &'s TS, let g = convert_graph_name(g, &mut buf_g);
p: &'s TP, if s.is_none() || p.is_none() || o.is_none() || g.is_none() {
o: &'s TO, Box::new(empty())
g: Option<&'s TG>, } else {
) -> DQuadSource<'s, Self> Box::new(self.quads_for_pattern(s, p, o, g).map(io_quad_map))
where }
TS: TTerm + ?Sized, }
TP: TTerm + ?Sized, fn subjects(&self) -> DResultTermSet<Self>
TO: TTerm + ?Sized, where
TG: TTerm + ?Sized, DTerm<Self>: Clone + Eq + Hash,
{ {
let mut buf_s = String::new(); sparql_to_hashset(
let s = convert_subject(s, &mut buf_s); self,
let mut buf_p = String::new(); "SELECT DISTINCT ?s {{?s ?p ?o} UNION { GRAPH ?g {?s ?p ?o}}}",
let p = convert_predicate(p, &mut buf_p); )
let mut buf_o = String::new(); }
let o = convert_object(o, &mut buf_o); fn predicates(&self) -> DResultTermSet<Self>
let mut buf_g = String::new(); where
let g = convert_graph_name(g, &mut buf_g); DTerm<Self>: Clone + Eq + Hash,
if s.is_none() || p.is_none() || o.is_none() || g.is_none() { {
Box::new(empty()) sparql_to_hashset(
} else { self,
Box::new(self.quads_for_pattern(s, p, o, g).map($quad_map)) "SELECT DISTINCT ?p {{?s ?p ?o} UNION { GRAPH ?g {?s ?p ?o}}}",
} )
} }
fn subjects(&self) -> DResultTermSet<Self> fn objects(&self) -> DResultTermSet<Self>
where where
DTerm<Self>: Clone + Eq + Hash, DTerm<Self>: Clone + Eq + Hash,
{ {
sparql_to_hashset!( sparql_to_hashset(
self, self,
$err_map, "SELECT DISTINCT ?o {{?s ?p ?o} UNION { GRAPH ?g {?s ?p ?o}}}",
"SELECT DISTINCT ?s {{?s ?p ?o} UNION { GRAPH ?g {?s ?p ?o}}}" )
) }
} fn graph_names(&self) -> DResultTermSet<Self>
fn predicates(&self) -> DResultTermSet<Self> where
where DTerm<Self>: Clone + Eq + Hash,
DTerm<Self>: Clone + Eq + Hash, {
{ sparql_to_hashset(self, "SELECT DISTINCT ?g {GRAPH ?g {?s ?p ?o}}")
sparql_to_hashset!( }
self, fn iris(&self) -> DResultTermSet<Self>
$err_map, where
"SELECT DISTINCT ?p {{?s ?p ?o} UNION { GRAPH ?g {?s ?p ?o}}}" DTerm<Self>: Clone + Eq + Hash,
) {
} sparql_to_hashset(
fn objects(&self) -> DResultTermSet<Self> self,
where "SELECT DISTINCT ?iri {
DTerm<Self>: Clone + Eq + Hash,
{
sparql_to_hashset!(
self,
$err_map,
"SELECT DISTINCT ?o {{?s ?p ?o} UNION { GRAPH ?g {?s ?p ?o}}}"
)
}
fn graph_names(&self) -> DResultTermSet<Self>
where
DTerm<Self>: Clone + Eq + Hash,
{
sparql_to_hashset!(self, $err_map, "SELECT DISTINCT ?g {GRAPH ?g {?s ?p ?o}}")
}
fn iris(&self) -> DResultTermSet<Self>
where
DTerm<Self>: Clone + Eq + Hash,
{
sparql_to_hashset!(
self,
$err_map,
"SELECT DISTINCT ?iri {
{?iri ?p ?o} UNION {?iri ?p ?o} UNION
{?s ?iri ?o} UNION {?s ?iri ?o} UNION
{?s ?p ?iri} UNION {?s ?p ?iri} UNION
@ -367,137 +333,119 @@ macro_rules! impl_dataset {
{GRAPH ?g {?s ?iri ?o}} UNION {GRAPH ?g {?s ?iri ?o}} UNION
{GRAPH ?g {?s ?p ?iri}} {GRAPH ?g {?s ?p ?iri}}
FILTER isIRI(?iri) FILTER isIRI(?iri)
}" }",
) )
} }
fn bnodes(&self) -> DResultTermSet<Self> fn bnodes(&self) -> DResultTermSet<Self>
where where
DTerm<Self>: Clone + Eq + Hash, DTerm<Self>: Clone + Eq + Hash,
{ {
sparql_to_hashset!( sparql_to_hashset(
self, self,
$err_map, "SELECT DISTINCT ?bn {
"SELECT DISTINCT ?bn {
{?bn ?p ?o} UNION {?bn ?p ?o} UNION
{?s ?p ?bn} UNION {?s ?p ?bn} UNION
{GRAPH ?bn {?s ?p ?o}} UNION {GRAPH ?bn {?s ?p ?o}} UNION
{GRAPH ?s {?bn ?p ?o}} UNION {GRAPH ?s {?bn ?p ?o}} UNION
{GRAPH ?g {?s ?p ?bn}} {GRAPH ?g {?s ?p ?bn}}
FILTER isBlank(?bn) FILTER isBlank(?bn)
}" }",
) )
} }
fn literals(&self) -> DResultTermSet<Self> fn literals(&self) -> DResultTermSet<Self>
where where
DTerm<Self>: Clone + Eq + Hash, DTerm<Self>: Clone + Eq + Hash,
{ {
sparql_to_hashset!( sparql_to_hashset(
self, self,
$err_map, "SELECT DISTINCT ?lit {
"SELECT DISTINCT ?lit {
{?s ?p ?lit} UNION {?s ?p ?lit} UNION
{ GRAPH ?g {?s ?p ?lit}} { GRAPH ?g {?s ?p ?lit}}
FILTER isLiteral(?lit) FILTER isLiteral(?lit)
}" }",
) )
} }
fn variables(&self) -> DResultTermSet<Self> fn variables(&self) -> DResultTermSet<Self>
where where
DTerm<Self>: Clone + Eq + Hash, DTerm<Self>: Clone + Eq + Hash,
{ {
Ok(std::collections::HashSet::new()) Ok(std::collections::HashSet::new())
} }
}
};
} }
mod sled { impl MutableDataset for SledStore {
use super::*; type MutationError = Error;
fn insert<TS, TP, TO, TG>(
impl_dataset!(SledStore, std::io::Error, io_quad_map, io_err_map); &mut self,
s: &TS,
impl MutableDataset for SledStore { p: &TP,
type MutationError = std::io::Error; o: &TO,
fn insert<TS, TP, TO, TG>( g: Option<&TG>,
&mut self, ) -> MDResult<Self, bool>
s: &TS, where
p: &TP, TS: TTerm + ?Sized,
o: &TO, TP: TTerm + ?Sized,
g: Option<&TG>, TO: TTerm + ?Sized,
) -> MDResult<Self, bool> TG: TTerm + ?Sized,
where {
TS: TTerm + ?Sized, let mut buf_s = String::new();
TP: TTerm + ?Sized, let mut buf_p = String::new();
TO: TTerm + ?Sized, let mut buf_o = String::new();
TG: TTerm + ?Sized, let mut buf_g = String::new();
{ let quadref =
let mut buf_s = String::new(); match convert_quadref(s, p, o, g, &mut buf_s, &mut buf_p, &mut buf_o, &mut buf_g) {
let mut buf_p = String::new(); Some(quad) => quad,
let mut buf_o = String::new(); None => return Ok(false),
let mut buf_g = String::new(); };
let quadref = SledStore::insert(self, quadref).map(|_| true)
match convert_quadref(s, p, o, g, &mut buf_s, &mut buf_p, &mut buf_o, &mut buf_g) {
Some(quad) => quad,
None => return Ok(false),
};
SledStore::insert(self, quadref).map(|_| true)
}
fn remove<TS, TP, TO, TG>(
&mut self,
s: &TS,
p: &TP,
o: &TO,
g: Option<&TG>,
) -> MDResult<Self, bool>
where
TS: TTerm + ?Sized,
TP: TTerm + ?Sized,
TO: TTerm + ?Sized,
TG: TTerm + ?Sized,
{
let mut buf_s = String::new();
let mut buf_p = String::new();
let mut buf_o = String::new();
let mut buf_g = String::new();
let quadref =
match convert_quadref(s, p, o, g, &mut buf_s, &mut buf_p, &mut buf_o, &mut buf_g) {
Some(quad) => quad,
None => return Ok(false),
};
SledStore::remove(self, quadref).map(|_| true)
}
} }
impl CollectibleDataset for SledStore { fn remove<TS, TP, TO, TG>(
fn from_quad_source<QS: QuadSource>( &mut self,
quads: QS, s: &TS,
) -> StreamResult<Self, QS::Error, Self::Error> { p: &TP,
let mut d = o: &TO,
SledStore::new().map_err(sophia_api::quad::stream::StreamError::SinkError)?; g: Option<&TG>,
d.insert_all(quads)?; ) -> MDResult<Self, bool>
Ok(d) where
} TS: TTerm + ?Sized,
TP: TTerm + ?Sized,
TO: TTerm + ?Sized,
TG: TTerm + ?Sized,
{
let mut buf_s = String::new();
let mut buf_p = String::new();
let mut buf_o = String::new();
let mut buf_g = String::new();
let quadref =
match convert_quadref(s, p, o, g, &mut buf_s, &mut buf_p, &mut buf_o, &mut buf_g) {
Some(quad) => quad,
None => return Ok(false),
};
SledStore::remove(self, quadref).map(|_| true)
} }
}
#[cfg(test)] impl CollectibleDataset for SledStore {
sophia_api::test_dataset_impl!(test, SledStore, false, false); fn from_quad_source<QS: QuadSource>(quads: QS) -> StreamResult<Self, QS::Error, Self::Error> {
let mut d = SledStore::new().map_err(sophia_api::quad::stream::StreamError::SinkError)?;
d.insert_all(quads)?;
Ok(d)
}
} }
// helper functions // helper functions
fn io_quad_map<'a>( fn io_quad_map<'a>(res: Result<Quad, Error>) -> Result<StreamedSophiaQuad<'a>, Error> {
res: Result<Quad, std::io::Error>,
) -> Result<StreamedSophiaQuad<'a>, std::io::Error> {
res.map(|q| { res.map(|q| {
let q: SophiaQuad = q.into(); let q: SophiaQuad = q.into();
StreamedQuad::by_value(q) StreamedQuad::by_value(q)
}) })
} }
fn io_err_map(err: EvaluationError) -> std::io::Error { fn io_err_map(err: EvaluationError) -> Error {
match err { match err {
EvaluationError::Io(err) => err, EvaluationError::Io(err) => err,
_ => panic!("Unexpected error"), err => Error::new(ErrorKind::InvalidInput, err),
} }
} }
@ -576,7 +524,7 @@ fn convert_iri_raw<'a>(
suffix: Option<&'a str>, suffix: Option<&'a str>,
buffer: &'a mut String, buffer: &'a mut String,
) -> NamedNodeRef<'a> { ) -> NamedNodeRef<'a> {
let iri: &'a str = match suffix { NamedNodeRef::new_unchecked(match suffix {
Some(suffix) => { Some(suffix) => {
buffer.clear(); buffer.clear();
buffer.push_str(ns); buffer.push_str(ns);
@ -584,8 +532,7 @@ fn convert_iri_raw<'a>(
buffer buffer
} }
None => ns, None => ns,
}; })
NamedNodeRef::new_unchecked(iri)
} }
fn convert_quadref<'a, TS, TP, TO, TG>( fn convert_quadref<'a, TS, TP, TO, TG>(
@ -622,3 +569,23 @@ where
}; };
Some(QuadRef::new(s, p, o, g)) Some(QuadRef::new(s, p, o, g))
} }
/// Execute a SPARQL query in a store, and return the result as a HashSet,
/// mapping the error (if any) through the given function.
///
/// # Precondition
/// + the query must be a SELECT query with a single selected variable
/// + it must not produce NULL results
fn sparql_to_hashset(store: &SledStore, sparql: &str) -> Result<HashSet<Term>, Error> {
if let QueryResults::Solutions(solutions) = store.query(sparql).map_err(io_err_map)? {
solutions
.map(|r| r.map(|v| v.get(0).unwrap().clone()))
.collect::<Result<_, _>>()
.map_err(io_err_map)
} else {
unreachable!()
}
}
#[cfg(test)]
sophia_api::test_dataset_impl!(test, SledStore, false, false);

Loading…
Cancel
Save