From 17a3ae728d2ce017bd34e763010c89abd2ba4b16 Mon Sep 17 00:00:00 2001 From: Tpt Date: Thu, 22 Apr 2021 10:11:29 +0200 Subject: [PATCH] Removes generics from SPARQL implementation --- lib/src/sparql/dataset.rs | 49 ++++---- lib/src/sparql/eval.rs | 105 ++++++----------- lib/src/sparql/mod.rs | 25 ++-- lib/src/sparql/plan_builder.rs | 19 +-- lib/src/sparql/update.rs | 209 ++++++++++++--------------------- lib/src/store/mod.rs | 23 ++-- lib/src/store/sled.rs | 23 ++-- lib/src/store/storage.rs | 26 ++++ 8 files changed, 206 insertions(+), 273 deletions(-) diff --git a/lib/src/sparql/dataset.rs b/lib/src/sparql/dataset.rs index 6c5e45e7..5b8fafa4 100644 --- a/lib/src/sparql/dataset.rs +++ b/lib/src/sparql/dataset.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 { - store: S, +pub(crate) struct DatasetView { + storage: Storage, extra: RefCell>, dataset: EncodedDatasetSpec, } -impl DatasetView { - pub fn new(store: S, dataset: &QueryDataset) -> Result { +impl DatasetView { + pub fn new(storage: Storage, dataset: &QueryDataset) -> Result { 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::, _>>() }) - .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::, _>>() }) - .transpose() - .map_err(|e| e.into())?, + .transpose()?, }; Ok(Self { - store, + storage, extra: RefCell::new(HashMap::default()), dataset, }) @@ -56,25 +55,23 @@ impl DatasetView { object: Option, graph_name: Option, ) -> impl Iterator> + '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 StrEncodingAware for DatasetView { +impl StrEncodingAware for DatasetView { type Error = EvaluationError; } -impl StrLookup for DatasetView { +impl StrLookup for DatasetView { fn get_str(&self, id: StrHash) -> Result, 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, EvaluationError> { @@ -82,12 +79,12 @@ impl StrLookup for DatasetView { 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 ReadableEncodedStore for DatasetView { +impl ReadableEncodedStore for DatasetView { type QuadsIter = Box>>; type GraphsIter = Once>; @@ -198,9 +195,9 @@ impl ReadableEncodedStore for DatasetView } } -impl<'a, S: ReadableEncodedStore> StrContainer for &'a DatasetView { +impl StrContainer for DatasetView { fn insert_str(&self, value: &str) -> Result { - 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); diff --git a/lib/src/sparql/eval.rs b/lib/src/sparql/eval.rs index 4a41553c..7a6b2b21 100644 --- a/lib/src/sparql/eval.rs +++ b/lib/src/sparql/eval.rs @@ -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>>; -pub(crate) struct SimpleEvaluator { - dataset: Rc, +#[derive(Clone)] +pub(crate) struct SimpleEvaluator { + dataset: Rc, base_iri: Option>>, now: DateTime, service_handler: Rc>, } -impl Clone for SimpleEvaluator { - 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 + 'static> SimpleEvaluator -where - for<'a> &'a S: StrContainer, -{ +impl SimpleEvaluator { pub fn new( - dataset: Rc, + dataset: Rc, base_iri: Option>>, service_handler: Rc>, ) -> 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 { - eval: SimpleEvaluator, +struct LeftJoinIterator { + eval: SimpleEvaluator, right_plan: Rc, left_iter: EncodedTuplesIterator, current_right: EncodedTuplesIterator, } -impl + 'static> Iterator for LeftJoinIterator -where - for<'a> &'a S: StrContainer, -{ +impl Iterator for LeftJoinIterator { type Item = Result; fn next(&mut self) -> Option> { @@ -2500,8 +2485,8 @@ where } } -struct BadLeftJoinIterator { - eval: SimpleEvaluator, +struct BadLeftJoinIterator { + eval: SimpleEvaluator, right_plan: Rc, left_iter: EncodedTuplesIterator, current_left: Option, @@ -2509,10 +2494,7 @@ struct BadLeftJoinIterator { problem_vars: Rc>, } -impl + 'static> Iterator for BadLeftJoinIterator -where - for<'a> &'a S: StrContainer, -{ +impl Iterator for BadLeftJoinIterator { type Item = Result; fn next(&mut self) -> Option> { @@ -2555,18 +2537,15 @@ where } } -struct UnionIterator { - eval: SimpleEvaluator, +struct UnionIterator { + eval: SimpleEvaluator, plans: Vec>, input: EncodedTuple, current_iterator: EncodedTuplesIterator, current_plan: usize, } -impl + 'static> Iterator for UnionIterator -where - for<'a> &'a S: StrContainer, -{ +impl Iterator for UnionIterator { type Item = Result; fn next(&mut self) -> Option> { @@ -2585,15 +2564,15 @@ where } } -struct ConstructIterator { - eval: SimpleEvaluator, +struct ConstructIterator { + eval: SimpleEvaluator, iter: EncodedTuplesIterator, template: Vec, buffered_results: Vec>, bnodes: Vec, } -impl + 'static> Iterator for ConstructIterator { +impl Iterator for ConstructIterator { type Item = Result; fn next(&mut self) -> Option> { @@ -2660,13 +2639,13 @@ fn decode_triple( )) } -struct DescribeIterator { - eval: SimpleEvaluator, +struct DescribeIterator { + eval: SimpleEvaluator, iter: EncodedTuplesIterator, quads: Box>>, } -impl + 'static> Iterator for DescribeIterator { +impl Iterator for DescribeIterator { type Item = Result; fn next(&mut self) -> Option> { @@ -2976,21 +2955,18 @@ impl Accumulator for AvgAccumulator { } #[allow(clippy::option_option)] -struct MinAccumulator { - eval: SimpleEvaluator, +struct MinAccumulator { + eval: SimpleEvaluator, min: Option>, } -impl MinAccumulator { - fn new(eval: SimpleEvaluator) -> Self { +impl MinAccumulator { + fn new(eval: SimpleEvaluator) -> Self { Self { eval, min: None } } } -impl + 'static> Accumulator for MinAccumulator -where - for<'a> &'a S: StrContainer, -{ +impl Accumulator for MinAccumulator { fn add(&mut self, element: Option) { 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 { - eval: SimpleEvaluator, +struct MaxAccumulator { + eval: SimpleEvaluator, max: Option>, } -impl MaxAccumulator { - fn new(eval: SimpleEvaluator) -> Self { +impl MaxAccumulator { + fn new(eval: SimpleEvaluator) -> Self { Self { eval, max: None } } } -impl + 'static> Accumulator for MaxAccumulator -where - for<'a> &'a S: StrContainer, -{ +impl Accumulator for MaxAccumulator { fn add(&mut self, element: Option) { 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 { - eval: SimpleEvaluator, +struct GroupConcatAccumulator { + eval: SimpleEvaluator, concat: Option, language: Option>, separator: Rc, } -impl GroupConcatAccumulator { - fn new(eval: SimpleEvaluator, separator: Rc) -> Self { +impl GroupConcatAccumulator { + fn new(eval: SimpleEvaluator, separator: Rc) -> Self { Self { eval, concat: Some("".to_owned()), @@ -3079,11 +3052,7 @@ impl GroupConcatAccumulator { } } -impl + 'static> Accumulator - for GroupConcatAccumulator -where - for<'a> &'a S: StrContainer, -{ +impl Accumulator for GroupConcatAccumulator { fn add(&mut self, element: Option) { if let Some(concat) = self.concat.as_mut() { if let Some(element) = element { diff --git a/lib/src/sparql/mod.rs b/lib/src/sparql/mod.rs index 4728513c..c84136f4 100644 --- a/lib/src/sparql/mod.rs +++ b/lib/src/sparql/mod.rs @@ -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( - store: R, +pub(crate) fn evaluate_query( + storage: Storage, query: impl TryInto>, options: QueryOptions, ) -> Result { 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 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>, -{ - 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) } diff --git a/lib/src/sparql/plan_builder.rs b/lib/src/sparql/plan_builder.rs index e3a75bac..66e4fc4a 100644 --- a/lib/src/sparql/plan_builder.rs +++ b/lib/src/sparql/plan_builder.rs @@ -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 { - encoder: E, +pub(crate) struct PlanBuilder<'a> { + dataset: &'a DatasetView, } -impl> PlanBuilder { +impl<'a> PlanBuilder<'a> { pub fn build( - encoder: E, + dataset: &'a DatasetView, pattern: &GraphPattern, ) -> Result<(PlanNode, Vec), 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> PlanBuilder { } pub fn build_graph_template( - encoder: E, + dataset: &'a DatasetView, template: &[TriplePattern], mut variables: Vec, ) -> Result, 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> PlanBuilder { } fn build_named_node(&mut self, node: &NamedNode) -> Result { - self.encoder + self.dataset .encode_named_node(NamedNodeRef::new_unchecked(node.iri.as_str())) } fn build_literal(&mut self, literal: &Literal) -> Result { - 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()) diff --git a/lib/src/sparql/update.rs b/lib/src/sparql/update.rs index b1ab80a5..964dc118 100644 --- a/lib/src/sparql/update.rs +++ b/lib/src/sparql/update.rs @@ -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>>, options: UpdateOptions, client: Client, } -impl< - 'a, - R: ReadableEncodedStore + Clone + 'static, - W: StrContainer + WritableEncodedStore + 'a, - > SimpleUpdateEvaluator<'a, R, W> -where - io::Error: From>, -{ +impl<'a> SimpleUpdateEvaluator<'a> { pub fn new( - read: R, - write: &'a mut W, + storage: &'a Storage, base_iri: Option>>, 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::>::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 { - 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 { - 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, 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, 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 { - e.into() -} diff --git a/lib/src/store/mod.rs b/lib/src/store/mod.rs index e9a61ea4..3a243922 100644 --- a/lib/src/store/mod.rs +++ b/lib/src/store/mod.rs @@ -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( - store: &mut S, +pub(crate) fn load_graph( + storage: &S, reader: impl BufRead, format: GraphFormat, to_graph_name: GraphNameRef<'_>, @@ -69,19 +70,19 @@ pub(crate) fn load_graph( }; 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( - store: &mut S, +fn load_from_triple_parser( + storage: &S, mut parser: P, to_graph_name: GraphNameRef<'_>, ) -> Result<(), StoreOrParseError> @@ -89,16 +90,14 @@ where StoreOrParseError: From, { 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(()) }) } diff --git a/lib/src/store/sled.rs b/lib/src/store/sled.rs index 52098f7b..a25facd8 100644 --- a/lib/src/store/sled.rs +++ b/lib/src/store/sled.rs @@ -112,7 +112,7 @@ impl SledStore { query: impl TryInto>, options: QueryOptions, ) -> Result { - 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>, 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>, 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(()) } diff --git a/lib/src/store/storage.rs b/lib/src/store/storage.rs index 25010db7..0fbd593c 100644 --- a/lib/src/store/storage.rs +++ b/lib/src/store/storage.rs @@ -1029,3 +1029,29 @@ impl<'a> StrContainer for StorageTransaction<'a> { Ok(key) } } + +pub(crate) trait StorageLike: StrLookup + StrContainer { + fn insert(&self, quad: &EncodedQuad) -> Result; + + fn remove(&self, quad: &EncodedQuad) -> Result; +} + +impl StorageLike for Storage { + fn insert(&self, quad: &EncodedQuad) -> Result { + self.insert(quad) + } + + fn remove(&self, quad: &EncodedQuad) -> Result { + self.remove(quad) + } +} + +impl<'a> StorageLike for StorageTransaction<'a> { + fn insert(&self, quad: &EncodedQuad) -> Result { + self.insert(quad) + } + + fn remove(&self, quad: &EncodedQuad) -> Result { + self.remove(quad) + } +}