Removes generics from SPARQL implementation

pull/171/head
Tpt 3 years ago
parent 5ea4f2f95a
commit 17a3ae728d
  1. 49
      lib/src/sparql/dataset.rs
  2. 105
      lib/src/sparql/eval.rs
  3. 25
      lib/src/sparql/mod.rs
  4. 19
      lib/src/sparql/plan_builder.rs
  5. 209
      lib/src/sparql/update.rs
  6. 23
      lib/src/store/mod.rs
  7. 23
      lib/src/store/sled.rs
  8. 26
      lib/src/store/storage.rs

@ -3,47 +3,46 @@ use crate::sparql::EvaluationError;
use crate::store::numeric_encoder::{
EncodedQuad, EncodedTerm, ReadEncoder, StrContainer, StrEncodingAware, StrHash, StrLookup,
};
use crate::store::storage::Storage;
use crate::store::ReadableEncodedStore;
use std::cell::RefCell;
use std::collections::HashMap;
use std::iter::{empty, once, Once};
pub(crate) struct DatasetView<S: ReadableEncodedStore> {
store: S,
pub(crate) struct DatasetView {
storage: Storage,
extra: RefCell<HashMap<StrHash, String>>,
dataset: EncodedDatasetSpec,
}
impl<S: ReadableEncodedStore> DatasetView<S> {
pub fn new(store: S, dataset: &QueryDataset) -> Result<Self, EvaluationError> {
impl DatasetView {
pub fn new(storage: Storage, dataset: &QueryDataset) -> Result<Self, EvaluationError> {
let dataset = EncodedDatasetSpec {
default: dataset
.default_graph_graphs()
.map(|graphs| {
graphs
.iter()
.flat_map(|g| store.get_encoded_graph_name(g.as_ref()).transpose())
.flat_map(|g| storage.get_encoded_graph_name(g.as_ref()).transpose())
.collect::<Result<Vec<_>, _>>()
})
.transpose()
.map_err(|e| e.into())?,
.transpose()?,
named: dataset
.available_named_graphs()
.map(|graphs| {
graphs
.iter()
.flat_map(|g| {
store
storage
.get_encoded_named_or_blank_node(g.as_ref())
.transpose()
})
.collect::<Result<Vec<_>, _>>()
})
.transpose()
.map_err(|e| e.into())?,
.transpose()?,
};
Ok(Self {
store,
storage,
extra: RefCell::new(HashMap::default()),
dataset,
})
@ -56,25 +55,23 @@ impl<S: ReadableEncodedStore> DatasetView<S> {
object: Option<EncodedTerm>,
graph_name: Option<EncodedTerm>,
) -> impl Iterator<Item = Result<EncodedQuad, EvaluationError>> + 'static {
self.store
.encoded_quads_for_pattern(subject, predicate, object, graph_name)
self.storage
.quads_for_pattern(subject, predicate, object, graph_name)
.map(|t| t.map_err(|e| e.into()))
}
}
impl<S: ReadableEncodedStore> StrEncodingAware for DatasetView<S> {
impl StrEncodingAware for DatasetView {
type Error = EvaluationError;
}
impl<S: ReadableEncodedStore> StrLookup for DatasetView<S> {
impl StrLookup for DatasetView {
fn get_str(&self, id: StrHash) -> Result<Option<String>, EvaluationError> {
self.extra
.borrow()
.get(&id)
.cloned()
.map(Ok)
.or_else(|| self.store.get_str(id).map_err(|e| e.into()).transpose())
.transpose()
Ok(if let Some(value) = self.extra.borrow().get(&id) {
Some(value.clone())
} else {
self.storage.get_str(id)?
})
}
fn get_str_id(&self, value: &str) -> Result<Option<StrHash>, EvaluationError> {
@ -82,12 +79,12 @@ impl<S: ReadableEncodedStore> StrLookup for DatasetView<S> {
Ok(if self.extra.borrow().contains_key(&id) {
Some(id)
} else {
self.store.get_str_id(value).map_err(|e| e.into())?
self.storage.get_str_id(value)?
})
}
}
impl<S: ReadableEncodedStore + 'static> ReadableEncodedStore for DatasetView<S> {
impl ReadableEncodedStore for DatasetView {
type QuadsIter = Box<dyn Iterator<Item = Result<EncodedQuad, EvaluationError>>>;
type GraphsIter = Once<Result<EncodedTerm, EvaluationError>>;
@ -198,9 +195,9 @@ impl<S: ReadableEncodedStore + 'static> ReadableEncodedStore for DatasetView<S>
}
}
impl<'a, S: ReadableEncodedStore> StrContainer for &'a DatasetView<S> {
impl StrContainer for DatasetView {
fn insert_str(&self, value: &str) -> Result<StrHash, EvaluationError> {
if let Some(hash) = self.store.get_str_id(value).map_err(|e| e.into())? {
if let Some(hash) = self.storage.get_str_id(value)? {
Ok(hash)
} else {
let hash = StrHash::new(value);

@ -3,6 +3,7 @@ use crate::model::xsd::*;
use crate::model::Triple;
use crate::model::{BlankNode, LiteralRef, NamedNodeRef};
use crate::sparql::algebra::{Query, QueryDataset};
use crate::sparql::dataset::DatasetView;
use crate::sparql::error::EvaluationError;
use crate::sparql::model::*;
use crate::sparql::plan::*;
@ -32,30 +33,17 @@ const REGEX_SIZE_LIMIT: usize = 1_000_000;
type EncodedTuplesIterator = Box<dyn Iterator<Item = Result<EncodedTuple, EvaluationError>>>;
pub(crate) struct SimpleEvaluator<S> {
dataset: Rc<S>,
#[derive(Clone)]
pub(crate) struct SimpleEvaluator {
dataset: Rc<DatasetView>,
base_iri: Option<Rc<Iri<String>>>,
now: DateTime,
service_handler: Rc<dyn ServiceHandler<Error = EvaluationError>>,
}
impl<S> Clone for SimpleEvaluator<S> {
fn clone(&self) -> Self {
Self {
dataset: self.dataset.clone(),
base_iri: self.base_iri.clone(),
now: self.now,
service_handler: self.service_handler.clone(),
}
}
}
impl<S: ReadableEncodedStore<Error = EvaluationError> + 'static> SimpleEvaluator<S>
where
for<'a> &'a S: StrContainer,
{
impl SimpleEvaluator {
pub fn new(
dataset: Rc<S>,
dataset: Rc<DatasetView>,
base_iri: Option<Rc<Iri<String>>>,
service_handler: Rc<dyn ServiceHandler<Error = EvaluationError>>,
) -> Self {
@ -1829,7 +1817,7 @@ where
put_variable_value(
variable,
&variables,
encoder.encode_term(term.as_ref()).map_err(|e| e.into())?,
encoder.encode_term(term.as_ref())?,
&mut encoded_terms,
)
}
@ -2469,17 +2457,14 @@ impl Iterator for AntiJoinIterator {
}
}
struct LeftJoinIterator<S: ReadableEncodedStore + 'static> {
eval: SimpleEvaluator<S>,
struct LeftJoinIterator {
eval: SimpleEvaluator,
right_plan: Rc<PlanNode>,
left_iter: EncodedTuplesIterator,
current_right: EncodedTuplesIterator,
}
impl<S: ReadableEncodedStore<Error = EvaluationError> + 'static> Iterator for LeftJoinIterator<S>
where
for<'a> &'a S: StrContainer,
{
impl Iterator for LeftJoinIterator {
type Item = Result<EncodedTuple, EvaluationError>;
fn next(&mut self) -> Option<Result<EncodedTuple, EvaluationError>> {
@ -2500,8 +2485,8 @@ where
}
}
struct BadLeftJoinIterator<S: ReadableEncodedStore + 'static> {
eval: SimpleEvaluator<S>,
struct BadLeftJoinIterator {
eval: SimpleEvaluator,
right_plan: Rc<PlanNode>,
left_iter: EncodedTuplesIterator,
current_left: Option<EncodedTuple>,
@ -2509,10 +2494,7 @@ struct BadLeftJoinIterator<S: ReadableEncodedStore + 'static> {
problem_vars: Rc<Vec<usize>>,
}
impl<S: ReadableEncodedStore<Error = EvaluationError> + 'static> Iterator for BadLeftJoinIterator<S>
where
for<'a> &'a S: StrContainer,
{
impl Iterator for BadLeftJoinIterator {
type Item = Result<EncodedTuple, EvaluationError>;
fn next(&mut self) -> Option<Result<EncodedTuple, EvaluationError>> {
@ -2555,18 +2537,15 @@ where
}
}
struct UnionIterator<S: ReadableEncodedStore + 'static> {
eval: SimpleEvaluator<S>,
struct UnionIterator {
eval: SimpleEvaluator,
plans: Vec<Rc<PlanNode>>,
input: EncodedTuple,
current_iterator: EncodedTuplesIterator,
current_plan: usize,
}
impl<S: ReadableEncodedStore<Error = EvaluationError> + 'static> Iterator for UnionIterator<S>
where
for<'a> &'a S: StrContainer,
{
impl Iterator for UnionIterator {
type Item = Result<EncodedTuple, EvaluationError>;
fn next(&mut self) -> Option<Result<EncodedTuple, EvaluationError>> {
@ -2585,15 +2564,15 @@ where
}
}
struct ConstructIterator<S: ReadableEncodedStore + 'static> {
eval: SimpleEvaluator<S>,
struct ConstructIterator {
eval: SimpleEvaluator,
iter: EncodedTuplesIterator,
template: Vec<TripleTemplate>,
buffered_results: Vec<Result<Triple, EvaluationError>>,
bnodes: Vec<EncodedTerm>,
}
impl<S: ReadableEncodedStore<Error = EvaluationError> + 'static> Iterator for ConstructIterator<S> {
impl Iterator for ConstructIterator {
type Item = Result<Triple, EvaluationError>;
fn next(&mut self) -> Option<Result<Triple, EvaluationError>> {
@ -2660,13 +2639,13 @@ fn decode_triple<D: Decoder>(
))
}
struct DescribeIterator<S: ReadableEncodedStore + 'static> {
eval: SimpleEvaluator<S>,
struct DescribeIterator {
eval: SimpleEvaluator,
iter: EncodedTuplesIterator,
quads: Box<dyn Iterator<Item = Result<EncodedQuad, EvaluationError>>>,
}
impl<S: ReadableEncodedStore<Error = EvaluationError> + 'static> Iterator for DescribeIterator<S> {
impl Iterator for DescribeIterator {
type Item = Result<Triple, EvaluationError>;
fn next(&mut self) -> Option<Result<Triple, EvaluationError>> {
@ -2976,21 +2955,18 @@ impl Accumulator for AvgAccumulator {
}
#[allow(clippy::option_option)]
struct MinAccumulator<S: ReadableEncodedStore + 'static> {
eval: SimpleEvaluator<S>,
struct MinAccumulator {
eval: SimpleEvaluator,
min: Option<Option<EncodedTerm>>,
}
impl<S: ReadableEncodedStore + 'static> MinAccumulator<S> {
fn new(eval: SimpleEvaluator<S>) -> Self {
impl MinAccumulator {
fn new(eval: SimpleEvaluator) -> Self {
Self { eval, min: None }
}
}
impl<S: ReadableEncodedStore<Error = EvaluationError> + 'static> Accumulator for MinAccumulator<S>
where
for<'a> &'a S: StrContainer,
{
impl Accumulator for MinAccumulator {
fn add(&mut self, element: Option<EncodedTerm>) {
if let Some(min) = self.min {
if self.eval.cmp_terms(element, min) == Ordering::Less {
@ -3007,21 +2983,18 @@ where
}
#[allow(clippy::option_option)]
struct MaxAccumulator<S: ReadableEncodedStore + 'static> {
eval: SimpleEvaluator<S>,
struct MaxAccumulator {
eval: SimpleEvaluator,
max: Option<Option<EncodedTerm>>,
}
impl<S: ReadableEncodedStore + 'static> MaxAccumulator<S> {
fn new(eval: SimpleEvaluator<S>) -> Self {
impl MaxAccumulator {
fn new(eval: SimpleEvaluator) -> Self {
Self { eval, max: None }
}
}
impl<S: ReadableEncodedStore<Error = EvaluationError> + 'static> Accumulator for MaxAccumulator<S>
where
for<'a> &'a S: StrContainer,
{
impl Accumulator for MaxAccumulator {
fn add(&mut self, element: Option<EncodedTerm>) {
if let Some(max) = self.max {
if self.eval.cmp_terms(element, max) == Ordering::Greater {
@ -3061,15 +3034,15 @@ impl Accumulator for SampleAccumulator {
}
#[allow(clippy::option_option)]
struct GroupConcatAccumulator<S: ReadableEncodedStore + 'static> {
eval: SimpleEvaluator<S>,
struct GroupConcatAccumulator {
eval: SimpleEvaluator,
concat: Option<String>,
language: Option<Option<SmallStringOrId>>,
separator: Rc<String>,
}
impl<S: ReadableEncodedStore + 'static> GroupConcatAccumulator<S> {
fn new(eval: SimpleEvaluator<S>, separator: Rc<String>) -> Self {
impl GroupConcatAccumulator {
fn new(eval: SimpleEvaluator, separator: Rc<String>) -> Self {
Self {
eval,
concat: Some("".to_owned()),
@ -3079,11 +3052,7 @@ impl<S: ReadableEncodedStore + 'static> GroupConcatAccumulator<S> {
}
}
impl<S: ReadableEncodedStore<Error = EvaluationError> + 'static> Accumulator
for GroupConcatAccumulator<S>
where
for<'a> &'a S: StrContainer,
{
impl Accumulator for GroupConcatAccumulator {
fn add(&mut self, element: Option<EncodedTerm>) {
if let Some(concat) = self.concat.as_mut() {
if let Some(element) = element {

@ -30,20 +30,18 @@ use crate::sparql::plan_builder::PlanBuilder;
pub use crate::sparql::service::ServiceHandler;
use crate::sparql::service::{EmptyServiceHandler, ErrorConversionServiceHandler};
use crate::sparql::update::SimpleUpdateEvaluator;
use crate::store::numeric_encoder::StrContainer;
use crate::store::{ReadableEncodedStore, StoreOrParseError, WritableEncodedStore};
use crate::store::storage::Storage;
pub use spargebra::ParseError;
use std::convert::TryInto;
use std::io;
use std::rc::Rc;
pub(crate) fn evaluate_query<R: ReadableEncodedStore + 'static>(
store: R,
pub(crate) fn evaluate_query(
storage: Storage,
query: impl TryInto<Query, Error = impl Into<EvaluationError>>,
options: QueryOptions,
) -> Result<QueryResults, EvaluationError> {
let query = query.try_into().map_err(|e| e.into())?;
let dataset = DatasetView::new(store, &query.dataset)?;
let dataset = DatasetView::new(storage, &query.dataset)?;
match query.inner {
spargebra::Query::Select {
pattern, base_iri, ..
@ -179,18 +177,11 @@ impl From<QueryOptions> for UpdateOptions {
}
}
pub(crate) fn evaluate_update<
R: ReadableEncodedStore + Clone + 'static,
W: StrContainer + WritableEncodedStore,
>(
read: R,
write: &mut W,
pub(crate) fn evaluate_update(
storage: &Storage,
update: Update,
options: UpdateOptions,
) -> Result<(), EvaluationError>
where
io::Error: From<StoreOrParseError<W::Error>>,
{
SimpleUpdateEvaluator::new(read, write, update.inner.base_iri.map(Rc::new), options)
) -> Result<(), EvaluationError> {
SimpleUpdateEvaluator::new(storage, update.inner.base_iri.map(Rc::new), options)
.eval_all(&update.inner.operations, &update.using_datasets)
}

@ -1,4 +1,5 @@
use crate::model::{LiteralRef, NamedNodeRef};
use crate::sparql::dataset::DatasetView;
use crate::sparql::error::EvaluationError;
use crate::sparql::model::Variable as OxVariable;
use crate::sparql::plan::*;
@ -9,17 +10,17 @@ use spargebra::term::*;
use std::collections::{BTreeSet, HashSet};
use std::rc::Rc;
pub(crate) struct PlanBuilder<E: WriteEncoder> {
encoder: E,
pub(crate) struct PlanBuilder<'a> {
dataset: &'a DatasetView,
}
impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
impl<'a> PlanBuilder<'a> {
pub fn build(
encoder: E,
dataset: &'a DatasetView,
pattern: &GraphPattern,
) -> Result<(PlanNode, Vec<Variable>), EvaluationError> {
let mut variables = Vec::default();
let plan = PlanBuilder { encoder }.build_for_graph_pattern(
let plan = PlanBuilder { dataset }.build_for_graph_pattern(
pattern,
&mut variables,
PatternValue::Constant(EncodedTerm::DefaultGraph),
@ -28,11 +29,11 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
}
pub fn build_graph_template(
encoder: E,
dataset: &'a DatasetView,
template: &[TriplePattern],
mut variables: Vec<Variable>,
) -> Result<Vec<TripleTemplate>, EvaluationError> {
PlanBuilder { encoder }.build_for_graph_template(template, &mut variables)
PlanBuilder { dataset }.build_for_graph_template(template, &mut variables)
}
fn build_for_graph_pattern(
@ -1047,12 +1048,12 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
}
fn build_named_node(&mut self, node: &NamedNode) -> Result<EncodedTerm, EvaluationError> {
self.encoder
self.dataset
.encode_named_node(NamedNodeRef::new_unchecked(node.iri.as_str()))
}
fn build_literal(&mut self, literal: &Literal) -> Result<EncodedTerm, EvaluationError> {
self.encoder.encode_literal(match literal {
self.dataset.encode_literal(match literal {
Literal::Simple { value } => LiteralRef::new_simple_literal(value),
Literal::LanguageTaggedString { value, language } => {
LiteralRef::new_language_tagged_literal_unchecked(value, language.as_str())

@ -8,10 +8,11 @@ use crate::sparql::http::Client;
use crate::sparql::plan::EncodedTuple;
use crate::sparql::plan_builder::PlanBuilder;
use crate::sparql::{EvaluationError, UpdateOptions};
use crate::store::load_graph;
use crate::store::numeric_encoder::{
EncodedQuad, EncodedTerm, ReadEncoder, StrContainer, StrLookup, WriteEncoder,
EncodedQuad, EncodedTerm, ReadEncoder, StrLookup, WriteEncoder,
};
use crate::store::{load_graph, ReadableEncodedStore, StoreOrParseError, WritableEncodedStore};
use crate::store::storage::Storage;
use http::header::{ACCEPT, CONTENT_TYPE, USER_AGENT};
use http::{Method, Request, StatusCode};
use oxiri::Iri;
@ -25,31 +26,21 @@ use std::collections::HashMap;
use std::io;
use std::rc::Rc;
pub(crate) struct SimpleUpdateEvaluator<'a, R, W> {
read: R,
write: &'a mut W,
pub(crate) struct SimpleUpdateEvaluator<'a> {
storage: &'a Storage,
base_iri: Option<Rc<Iri<String>>>,
options: UpdateOptions,
client: Client,
}
impl<
'a,
R: ReadableEncodedStore + Clone + 'static,
W: StrContainer + WritableEncodedStore + 'a,
> SimpleUpdateEvaluator<'a, R, W>
where
io::Error: From<StoreOrParseError<W::Error>>,
{
impl<'a> SimpleUpdateEvaluator<'a> {
pub fn new(
read: R,
write: &'a mut W,
storage: &'a Storage,
base_iri: Option<Rc<Iri<String>>>,
options: UpdateOptions,
) -> Self {
Self {
read,
write,
storage,
base_iri,
options,
client: Client::new(),
@ -102,7 +93,7 @@ where
let mut bnodes = HashMap::new();
for quad in data {
if let Some(quad) = self.encode_quad_for_insertion(quad, &mut bnodes)? {
self.write.insert_encoded(&quad).map_err(to_eval_error)?;
self.storage.insert(&quad)?;
}
}
Ok(())
@ -111,7 +102,7 @@ where
fn eval_delete_data(&mut self, data: &[Quad]) -> Result<(), EvaluationError> {
for quad in data {
if let Some(quad) = self.encode_quad_for_deletion(quad)? {
self.write.remove_encoded(&quad).map_err(to_eval_error)?;
self.storage.remove(&quad)?;
}
}
Ok(())
@ -124,9 +115,9 @@ where
using: &QueryDataset,
algebra: &GraphPattern,
) -> Result<(), EvaluationError> {
let dataset = Rc::new(DatasetView::new(self.read.clone(), using)?);
let dataset = Rc::new(DatasetView::new(self.storage.clone(), using)?);
let (plan, variables) = PlanBuilder::build(dataset.as_ref(), algebra)?;
let evaluator = SimpleEvaluator::<DatasetView<R>>::new(
let evaluator = SimpleEvaluator::new(
dataset.clone(),
self.base_iri.clone(),
self.options.query_options.service_handler.clone(),
@ -138,22 +129,16 @@ where
.into_iter()
.map(|t| {
Ok(if let Some(t) = t {
t.on_each_id(|id| {
self.write
.insert_str(
&dataset
.get_str(id)
.map_err(to_eval_error)?
.ok_or_else(|| {
EvaluationError::msg(
"String not stored in the string store",
)
})
.map_err(to_eval_error)?,
)
.map(|_| ())
.map_err(to_eval_error)
})?;
let r: Result<_, EvaluationError> = t.on_each_id(|id| {
self.storage.insert_str(
id,
&dataset.get_str(id)?.ok_or_else(|| {
EvaluationError::msg("String not stored in the string store")
})?,
)?;
Ok(())
});
r?;
Some(t)
} else {
None
@ -165,14 +150,14 @@ where
if let Some(quad) =
self.encode_quad_pattern_for_deletion(quad, &variables, &tuple)?
{
self.write.remove_encoded(&quad).map_err(to_eval_error)?;
self.storage.remove(&quad)?;
}
}
for quad in insert {
if let Some(quad) =
self.encode_quad_pattern_for_insertion(quad, &variables, &tuple, &mut bnodes)?
{
self.write.insert_encoded(&quad).map_err(to_eval_error)?;
self.storage.insert(&quad)?;
}
}
bnodes.clear();
@ -223,7 +208,7 @@ where
GraphNameRef::DefaultGraph
};
load_graph(
self.write,
self.storage,
response.into_body(),
format,
to_graph_name,
@ -235,11 +220,7 @@ where
fn eval_create(&mut self, graph: &NamedNode, silent: bool) -> Result<(), EvaluationError> {
let encoded_graph_name = self.encode_named_node_for_insertion(graph)?;
if self
.read
.contains_encoded_named_graph(encoded_graph_name)
.map_err(to_eval_error)?
{
if self.storage.contains_named_graph(encoded_graph_name)? {
if silent {
Ok(())
} else {
@ -249,9 +230,8 @@ where
)))
}
} else {
self.write
.insert_encoded_named_graph(encoded_graph_name)
.map_err(to_eval_error)
self.storage.insert_named_graph(encoded_graph_name)?;
Ok(())
}
}
@ -259,15 +239,8 @@ where
match graph {
GraphTarget::NamedNode(graph_name) => {
if let Some(graph_name) = self.encode_named_node_for_deletion(graph_name)? {
if self
.read
.contains_encoded_named_graph(graph_name)
.map_err(to_eval_error)?
{
return self
.write
.clear_encoded_graph(graph_name)
.map_err(to_eval_error);
if self.storage.contains_named_graph(graph_name)? {
return Ok(self.storage.clear_graph(graph_name)?);
}
}
if silent {
@ -279,29 +252,20 @@ where
)))
}
}
GraphTarget::DefaultGraph => self
.write
.clear_encoded_graph(EncodedTerm::DefaultGraph)
.map_err(to_eval_error),
GraphTarget::DefaultGraph => Ok(self.storage.clear_graph(EncodedTerm::DefaultGraph)?),
GraphTarget::NamedGraphs => {
// TODO: optimize?
for graph in self.read.encoded_named_graphs() {
self.write
.clear_encoded_graph(graph.map_err(to_eval_error)?)
.map_err(to_eval_error)?;
for graph in self.storage.named_graphs() {
self.storage.clear_graph(graph?)?;
}
Ok(())
}
GraphTarget::AllGraphs => {
// TODO: optimize?
for graph in self.read.encoded_named_graphs() {
self.write
.clear_encoded_graph(graph.map_err(to_eval_error)?)
.map_err(to_eval_error)?;
for graph in self.storage.named_graphs() {
self.storage.clear_graph(graph?)?;
}
self.write
.clear_encoded_graph(EncodedTerm::DefaultGraph)
.map_err(to_eval_error)
Ok(self.storage.clear_graph(EncodedTerm::DefaultGraph)?)
}
}
}
@ -310,15 +274,9 @@ where
match graph {
GraphTarget::NamedNode(graph_name) => {
if let Some(graph_name) = self.encode_named_node_for_deletion(graph_name)? {
if self
.read
.contains_encoded_named_graph(graph_name)
.map_err(to_eval_error)?
{
return self
.write
.remove_encoded_named_graph(graph_name)
.map_err(to_eval_error);
if self.storage.contains_named_graph(graph_name)? {
self.storage.remove_named_graph(graph_name)?;
return Ok(());
}
}
if silent {
@ -330,20 +288,15 @@ where
)))
}
}
GraphTarget::DefaultGraph => self
.write
.clear_encoded_graph(EncodedTerm::DefaultGraph)
.map_err(to_eval_error),
GraphTarget::DefaultGraph => Ok(self.storage.clear_graph(EncodedTerm::DefaultGraph)?),
GraphTarget::NamedGraphs => {
// TODO: optimize?
for graph in self.read.encoded_named_graphs() {
self.write
.remove_encoded_named_graph(graph.map_err(to_eval_error)?)
.map_err(to_eval_error)?;
for graph in self.storage.named_graphs() {
self.storage.remove_named_graph(graph?)?;
}
Ok(())
}
GraphTarget::AllGraphs => self.write.clear().map_err(to_eval_error),
GraphTarget::AllGraphs => Ok(self.storage.clear()?),
}
}
@ -358,20 +311,17 @@ where
self.encode_named_node_for_insertion(subject)?
}
NamedOrBlankNode::BlankNode(subject) => self
.write
.encode_blank_node(bnodes.entry(subject.clone()).or_default().as_ref())
.map_err(to_eval_error)?,
.storage
.encode_blank_node(bnodes.entry(subject.clone()).or_default().as_ref())?,
},
predicate: self
.write
.encode_named_node(NamedNodeRef::new_unchecked(&quad.predicate.iri))
.map_err(to_eval_error)?,
.storage
.encode_named_node(NamedNodeRef::new_unchecked(&quad.predicate.iri))?,
object: match &quad.object {
Term::NamedNode(object) => self.encode_named_node_for_insertion(object)?,
Term::BlankNode(object) => self
.write
.encode_blank_node(bnodes.entry(object.clone()).or_default().as_ref())
.map_err(to_eval_error)?,
.storage
.encode_blank_node(bnodes.entry(object.clone()).or_default().as_ref())?,
Term::Literal(object) => self.encode_literal_for_insertion(object)?,
},
graph_name: match &quad.graph_name {
@ -446,9 +396,8 @@ where
TermOrVariable::Term(term) => Some(match term {
Term::NamedNode(term) => self.encode_named_node_for_insertion(term)?,
Term::BlankNode(bnode) => self
.write
.encode_blank_node(bnodes.entry(bnode.clone()).or_default().as_ref())
.map_err(to_eval_error)?,
.storage
.encode_blank_node(bnodes.entry(bnode.clone()).or_default().as_ref())?,
Term::Literal(term) => self.encode_literal_for_insertion(term)?,
}),
TermOrVariable::Variable(v) => {
@ -501,26 +450,24 @@ where
&mut self,
term: &NamedNode,
) -> Result<EncodedTerm, EvaluationError> {
self.write
.encode_named_node(NamedNodeRef::new_unchecked(&term.iri))
.map_err(to_eval_error)
Ok(self
.storage
.encode_named_node(NamedNodeRef::new_unchecked(&term.iri))?)
}
fn encode_literal_for_insertion(
&mut self,
term: &Literal,
) -> Result<EncodedTerm, EvaluationError> {
self.write
.encode_literal(match term {
Literal::Simple { value } => LiteralRef::new_simple_literal(value),
Literal::LanguageTaggedString { value, language } => {
LiteralRef::new_language_tagged_literal_unchecked(value, language)
}
Literal::Typed { value, datatype } => {
LiteralRef::new_typed_literal(value, NamedNodeRef::new_unchecked(&datatype.iri))
}
})
.map_err(to_eval_error)
Ok(self.storage.encode_literal(match term {
Literal::Simple { value } => LiteralRef::new_simple_literal(value),
Literal::LanguageTaggedString { value, language } => {
LiteralRef::new_language_tagged_literal_unchecked(value, language)
}
Literal::Typed { value, datatype } => {
LiteralRef::new_typed_literal(value, NamedNodeRef::new_unchecked(&datatype.iri))
}
})?)
}
fn encode_quad_for_deletion(
@ -675,29 +622,23 @@ where
&self,
term: &NamedNode,
) -> Result<Option<EncodedTerm>, EvaluationError> {
self.read
.get_encoded_named_node(NamedNodeRef::new_unchecked(&term.iri))
.map_err(to_eval_error)
Ok(self
.storage
.get_encoded_named_node(NamedNodeRef::new_unchecked(&term.iri))?)
}
fn encode_literal_for_deletion(
&self,
term: &Literal,
) -> Result<Option<EncodedTerm>, EvaluationError> {
self.read
.get_encoded_literal(match term {
Literal::Simple { value } => LiteralRef::new_simple_literal(value),
Literal::LanguageTaggedString { value, language } => {
LiteralRef::new_language_tagged_literal_unchecked(value, language)
}
Literal::Typed { value, datatype } => {
LiteralRef::new_typed_literal(value, NamedNodeRef::new_unchecked(&datatype.iri))
}
})
.map_err(to_eval_error)
Ok(self.storage.get_encoded_literal(match term {
Literal::Simple { value } => LiteralRef::new_simple_literal(value),
Literal::LanguageTaggedString { value, language } => {
LiteralRef::new_language_tagged_literal_unchecked(value, language)
}
Literal::Typed { value, datatype } => {
LiteralRef::new_typed_literal(value, NamedNodeRef::new_unchecked(&datatype.iri))
}
})?)
}
}
fn to_eval_error(e: impl Into<EvaluationError>) -> EvaluationError {
e.into()
}

@ -14,6 +14,7 @@ use crate::error::invalid_input_error;
use crate::io::{DatasetFormat, DatasetSerializer, GraphFormat, GraphSerializer};
use crate::model::*;
use crate::store::numeric_encoder::*;
use crate::store::storage::StorageLike;
use oxiri::Iri;
use rio_api::parser::{QuadsParser, TriplesParser};
use rio_turtle::{NQuadsParser, NTriplesParser, TriGParser, TurtleError, TurtleParser};
@ -55,8 +56,8 @@ pub(crate) trait WritableEncodedStore: StrEncodingAware {
fn clear(&mut self) -> Result<(), Self::Error>;
}
pub(crate) fn load_graph<S: WritableEncodedStore + StrContainer>(
store: &mut S,
pub(crate) fn load_graph<S: StorageLike>(
storage: &S,
reader: impl BufRead,
format: GraphFormat,
to_graph_name: GraphNameRef<'_>,
@ -69,19 +70,19 @@ pub(crate) fn load_graph<S: WritableEncodedStore + StrContainer>(
};
match format {
GraphFormat::NTriples => {
load_from_triple_parser(store, NTriplesParser::new(reader), to_graph_name)
load_from_triple_parser(storage, NTriplesParser::new(reader), to_graph_name)
}
GraphFormat::Turtle => {
load_from_triple_parser(store, TurtleParser::new(reader, base_iri), to_graph_name)
load_from_triple_parser(storage, TurtleParser::new(reader, base_iri), to_graph_name)
}
GraphFormat::RdfXml => {
load_from_triple_parser(store, RdfXmlParser::new(reader, base_iri), to_graph_name)
load_from_triple_parser(storage, RdfXmlParser::new(reader, base_iri), to_graph_name)
}
}
}
fn load_from_triple_parser<S: WritableEncodedStore + StrContainer, P: TriplesParser>(
store: &mut S,
fn load_from_triple_parser<S: StorageLike, P: TriplesParser>(
storage: &S,
mut parser: P,
to_graph_name: GraphNameRef<'_>,
) -> Result<(), StoreOrParseError<S::Error>>
@ -89,16 +90,14 @@ where
StoreOrParseError<S::Error>: From<P::Error>,
{
let mut bnode_map = HashMap::default();
let to_graph_name = store
let to_graph_name = storage
.encode_graph_name(to_graph_name)
.map_err(StoreOrParseError::Store)?;
parser.parse_all(&mut move |t| {
let quad = store
let quad = storage
.encode_rio_triple_in_graph(t, to_graph_name, &mut bnode_map)
.map_err(StoreOrParseError::Store)?;
store
.insert_encoded(&quad)
.map_err(StoreOrParseError::Store)?;
storage.insert(&quad).map_err(StoreOrParseError::Store)?;
Ok(())
})
}

@ -112,7 +112,7 @@ impl SledStore {
query: impl TryInto<Query, Error = impl Into<EvaluationError>>,
options: QueryOptions,
) -> Result<QueryResults, EvaluationError> {
evaluate_query(self.clone(), query, options)
evaluate_query(self.storage.clone(), query, options)
}
/// Retrieves quads with a filter on each quad component
@ -213,8 +213,7 @@ impl SledStore {
options: UpdateOptions,
) -> Result<(), EvaluationError> {
evaluate_update(
self.clone(),
&mut &*self,
&self.storage,
update.try_into().map_err(|e| e.into())?,
options,
)
@ -290,8 +289,13 @@ impl SledStore {
to_graph_name: impl Into<GraphNameRef<'a>>,
base_iri: Option<&str>,
) -> Result<(), io::Error> {
let mut this = self;
load_graph(&mut this, reader, format, to_graph_name.into(), base_iri)?;
load_graph(
&self.storage,
reader,
format,
to_graph_name.into(),
base_iri,
)?;
Ok(())
}
@ -698,8 +702,13 @@ impl SledTransaction<'_> {
to_graph_name: impl Into<GraphNameRef<'a>>,
base_iri: Option<&str>,
) -> Result<(), SledUnabortableTransactionError> {
let mut this = self;
load_graph(&mut this, reader, format, to_graph_name.into(), base_iri)?;
load_graph(
&self.storage,
reader,
format,
to_graph_name.into(),
base_iri,
)?;
Ok(())
}

@ -1029,3 +1029,29 @@ impl<'a> StrContainer for StorageTransaction<'a> {
Ok(key)
}
}
pub(crate) trait StorageLike: StrLookup + StrContainer {
fn insert(&self, quad: &EncodedQuad) -> Result<bool, Self::Error>;
fn remove(&self, quad: &EncodedQuad) -> Result<bool, Self::Error>;
}
impl StorageLike for Storage {
fn insert(&self, quad: &EncodedQuad) -> Result<bool, Self::Error> {
self.insert(quad)
}
fn remove(&self, quad: &EncodedQuad) -> Result<bool, Self::Error> {
self.remove(quad)
}
}
impl<'a> StorageLike for StorageTransaction<'a> {
fn insert(&self, quad: &EncodedQuad) -> Result<bool, Self::Error> {
self.insert(quad)
}
fn remove(&self, quad: &EncodedQuad) -> Result<bool, Self::Error> {
self.remove(quad)
}
}

Loading…
Cancel
Save