Removes generics from SPARQL implementation

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

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

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

@ -1,4 +1,5 @@
use crate::model::{LiteralRef, NamedNodeRef}; use crate::model::{LiteralRef, NamedNodeRef};
use crate::sparql::dataset::DatasetView;
use crate::sparql::error::EvaluationError; use crate::sparql::error::EvaluationError;
use crate::sparql::model::Variable as OxVariable; use crate::sparql::model::Variable as OxVariable;
use crate::sparql::plan::*; use crate::sparql::plan::*;
@ -9,17 +10,17 @@ use spargebra::term::*;
use std::collections::{BTreeSet, HashSet}; use std::collections::{BTreeSet, HashSet};
use std::rc::Rc; use std::rc::Rc;
pub(crate) struct PlanBuilder<E: WriteEncoder> { pub(crate) struct PlanBuilder<'a> {
encoder: E, dataset: &'a DatasetView,
} }
impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> { impl<'a> PlanBuilder<'a> {
pub fn build( pub fn build(
encoder: E, dataset: &'a DatasetView,
pattern: &GraphPattern, pattern: &GraphPattern,
) -> Result<(PlanNode, Vec<Variable>), EvaluationError> { ) -> Result<(PlanNode, Vec<Variable>), EvaluationError> {
let mut variables = Vec::default(); let mut variables = Vec::default();
let plan = PlanBuilder { encoder }.build_for_graph_pattern( let plan = PlanBuilder { dataset }.build_for_graph_pattern(
pattern, pattern,
&mut variables, &mut variables,
PatternValue::Constant(EncodedTerm::DefaultGraph), PatternValue::Constant(EncodedTerm::DefaultGraph),
@ -28,11 +29,11 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
} }
pub fn build_graph_template( pub fn build_graph_template(
encoder: E, dataset: &'a DatasetView,
template: &[TriplePattern], template: &[TriplePattern],
mut variables: Vec<Variable>, mut variables: Vec<Variable>,
) -> Result<Vec<TripleTemplate>, EvaluationError> { ) -> 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( 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> { 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())) .encode_named_node(NamedNodeRef::new_unchecked(node.iri.as_str()))
} }
fn build_literal(&mut self, literal: &Literal) -> Result<EncodedTerm, EvaluationError> { 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::Simple { value } => LiteralRef::new_simple_literal(value),
Literal::LanguageTaggedString { value, language } => { Literal::LanguageTaggedString { value, language } => {
LiteralRef::new_language_tagged_literal_unchecked(value, language.as_str()) 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::EncodedTuple;
use crate::sparql::plan_builder::PlanBuilder; use crate::sparql::plan_builder::PlanBuilder;
use crate::sparql::{EvaluationError, UpdateOptions}; use crate::sparql::{EvaluationError, UpdateOptions};
use crate::store::load_graph;
use crate::store::numeric_encoder::{ 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::header::{ACCEPT, CONTENT_TYPE, USER_AGENT};
use http::{Method, Request, StatusCode}; use http::{Method, Request, StatusCode};
use oxiri::Iri; use oxiri::Iri;
@ -25,31 +26,21 @@ use std::collections::HashMap;
use std::io; use std::io;
use std::rc::Rc; use std::rc::Rc;
pub(crate) struct SimpleUpdateEvaluator<'a, R, W> { pub(crate) struct SimpleUpdateEvaluator<'a> {
read: R, storage: &'a Storage,
write: &'a mut W,
base_iri: Option<Rc<Iri<String>>>, base_iri: Option<Rc<Iri<String>>>,
options: UpdateOptions, options: UpdateOptions,
client: Client, client: Client,
} }
impl< impl<'a> SimpleUpdateEvaluator<'a> {
'a,
R: ReadableEncodedStore + Clone + 'static,
W: StrContainer + WritableEncodedStore + 'a,
> SimpleUpdateEvaluator<'a, R, W>
where
io::Error: From<StoreOrParseError<W::Error>>,
{
pub fn new( pub fn new(
read: R, storage: &'a Storage,
write: &'a mut W,
base_iri: Option<Rc<Iri<String>>>, base_iri: Option<Rc<Iri<String>>>,
options: UpdateOptions, options: UpdateOptions,
) -> Self { ) -> Self {
Self { Self {
read, storage,
write,
base_iri, base_iri,
options, options,
client: Client::new(), client: Client::new(),
@ -102,7 +93,7 @@ where
let mut bnodes = HashMap::new(); let mut bnodes = HashMap::new();
for quad in data { for quad in data {
if let Some(quad) = self.encode_quad_for_insertion(quad, &mut bnodes)? { 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(()) Ok(())
@ -111,7 +102,7 @@ where
fn eval_delete_data(&mut self, data: &[Quad]) -> Result<(), EvaluationError> { fn eval_delete_data(&mut self, data: &[Quad]) -> Result<(), EvaluationError> {
for quad in data { for quad in data {
if let Some(quad) = self.encode_quad_for_deletion(quad)? { 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(()) Ok(())
@ -124,9 +115,9 @@ where
using: &QueryDataset, using: &QueryDataset,
algebra: &GraphPattern, algebra: &GraphPattern,
) -> Result<(), EvaluationError> { ) -> 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 (plan, variables) = PlanBuilder::build(dataset.as_ref(), algebra)?;
let evaluator = SimpleEvaluator::<DatasetView<R>>::new( let evaluator = SimpleEvaluator::new(
dataset.clone(), dataset.clone(),
self.base_iri.clone(), self.base_iri.clone(),
self.options.query_options.service_handler.clone(), self.options.query_options.service_handler.clone(),
@ -138,22 +129,16 @@ where
.into_iter() .into_iter()
.map(|t| { .map(|t| {
Ok(if let Some(t) = t { Ok(if let Some(t) = t {
t.on_each_id(|id| { let r: Result<_, EvaluationError> = t.on_each_id(|id| {
self.write self.storage.insert_str(
.insert_str( id,
&dataset &dataset.get_str(id)?.ok_or_else(|| {
.get_str(id) EvaluationError::msg("String not stored in the string store")
.map_err(to_eval_error)? })?,
.ok_or_else(|| { )?;
EvaluationError::msg( Ok(())
"String not stored in the string store", });
) r?;
})
.map_err(to_eval_error)?,
)
.map(|_| ())
.map_err(to_eval_error)
})?;
Some(t) Some(t)
} else { } else {
None None
@ -165,14 +150,14 @@ where
if let Some(quad) = if let Some(quad) =
self.encode_quad_pattern_for_deletion(quad, &variables, &tuple)? 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 { for quad in insert {
if let Some(quad) = if let Some(quad) =
self.encode_quad_pattern_for_insertion(quad, &variables, &tuple, &mut bnodes)? 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(); bnodes.clear();
@ -223,7 +208,7 @@ where
GraphNameRef::DefaultGraph GraphNameRef::DefaultGraph
}; };
load_graph( load_graph(
self.write, self.storage,
response.into_body(), response.into_body(),
format, format,
to_graph_name, to_graph_name,
@ -235,11 +220,7 @@ where
fn eval_create(&mut self, graph: &NamedNode, silent: bool) -> Result<(), EvaluationError> { fn eval_create(&mut self, graph: &NamedNode, silent: bool) -> Result<(), EvaluationError> {
let encoded_graph_name = self.encode_named_node_for_insertion(graph)?; let encoded_graph_name = self.encode_named_node_for_insertion(graph)?;
if self if self.storage.contains_named_graph(encoded_graph_name)? {
.read
.contains_encoded_named_graph(encoded_graph_name)
.map_err(to_eval_error)?
{
if silent { if silent {
Ok(()) Ok(())
} else { } else {
@ -249,9 +230,8 @@ where
))) )))
} }
} else { } else {
self.write self.storage.insert_named_graph(encoded_graph_name)?;
.insert_encoded_named_graph(encoded_graph_name) Ok(())
.map_err(to_eval_error)
} }
} }
@ -259,15 +239,8 @@ where
match graph { match graph {
GraphTarget::NamedNode(graph_name) => { GraphTarget::NamedNode(graph_name) => {
if let Some(graph_name) = self.encode_named_node_for_deletion(graph_name)? { if let Some(graph_name) = self.encode_named_node_for_deletion(graph_name)? {
if self if self.storage.contains_named_graph(graph_name)? {
.read return Ok(self.storage.clear_graph(graph_name)?);
.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 silent { if silent {
@ -279,29 +252,20 @@ where
))) )))
} }
} }
GraphTarget::DefaultGraph => self GraphTarget::DefaultGraph => Ok(self.storage.clear_graph(EncodedTerm::DefaultGraph)?),
.write
.clear_encoded_graph(EncodedTerm::DefaultGraph)
.map_err(to_eval_error),
GraphTarget::NamedGraphs => { GraphTarget::NamedGraphs => {
// TODO: optimize? // TODO: optimize?
for graph in self.read.encoded_named_graphs() { for graph in self.storage.named_graphs() {
self.write self.storage.clear_graph(graph?)?;
.clear_encoded_graph(graph.map_err(to_eval_error)?)
.map_err(to_eval_error)?;
} }
Ok(()) Ok(())
} }
GraphTarget::AllGraphs => { GraphTarget::AllGraphs => {
// TODO: optimize? // TODO: optimize?
for graph in self.read.encoded_named_graphs() { for graph in self.storage.named_graphs() {
self.write self.storage.clear_graph(graph?)?;
.clear_encoded_graph(graph.map_err(to_eval_error)?)
.map_err(to_eval_error)?;
} }
self.write Ok(self.storage.clear_graph(EncodedTerm::DefaultGraph)?)
.clear_encoded_graph(EncodedTerm::DefaultGraph)
.map_err(to_eval_error)
} }
} }
} }
@ -310,15 +274,9 @@ where
match graph { match graph {
GraphTarget::NamedNode(graph_name) => { GraphTarget::NamedNode(graph_name) => {
if let Some(graph_name) = self.encode_named_node_for_deletion(graph_name)? { if let Some(graph_name) = self.encode_named_node_for_deletion(graph_name)? {
if self if self.storage.contains_named_graph(graph_name)? {
.read self.storage.remove_named_graph(graph_name)?;
.contains_encoded_named_graph(graph_name) return Ok(());
.map_err(to_eval_error)?
{
return self
.write
.remove_encoded_named_graph(graph_name)
.map_err(to_eval_error);
} }
} }
if silent { if silent {
@ -330,20 +288,15 @@ where
))) )))
} }
} }
GraphTarget::DefaultGraph => self GraphTarget::DefaultGraph => Ok(self.storage.clear_graph(EncodedTerm::DefaultGraph)?),
.write
.clear_encoded_graph(EncodedTerm::DefaultGraph)
.map_err(to_eval_error),
GraphTarget::NamedGraphs => { GraphTarget::NamedGraphs => {
// TODO: optimize? // TODO: optimize?
for graph in self.read.encoded_named_graphs() { for graph in self.storage.named_graphs() {
self.write self.storage.remove_named_graph(graph?)?;
.remove_encoded_named_graph(graph.map_err(to_eval_error)?)
.map_err(to_eval_error)?;
} }
Ok(()) 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)? self.encode_named_node_for_insertion(subject)?
} }
NamedOrBlankNode::BlankNode(subject) => self NamedOrBlankNode::BlankNode(subject) => self
.write .storage
.encode_blank_node(bnodes.entry(subject.clone()).or_default().as_ref()) .encode_blank_node(bnodes.entry(subject.clone()).or_default().as_ref())?,
.map_err(to_eval_error)?,
}, },
predicate: self predicate: self
.write .storage
.encode_named_node(NamedNodeRef::new_unchecked(&quad.predicate.iri)) .encode_named_node(NamedNodeRef::new_unchecked(&quad.predicate.iri))?,
.map_err(to_eval_error)?,
object: match &quad.object { object: match &quad.object {
Term::NamedNode(object) => self.encode_named_node_for_insertion(object)?, Term::NamedNode(object) => self.encode_named_node_for_insertion(object)?,
Term::BlankNode(object) => self Term::BlankNode(object) => self
.write .storage
.encode_blank_node(bnodes.entry(object.clone()).or_default().as_ref()) .encode_blank_node(bnodes.entry(object.clone()).or_default().as_ref())?,
.map_err(to_eval_error)?,
Term::Literal(object) => self.encode_literal_for_insertion(object)?, Term::Literal(object) => self.encode_literal_for_insertion(object)?,
}, },
graph_name: match &quad.graph_name { graph_name: match &quad.graph_name {
@ -446,9 +396,8 @@ where
TermOrVariable::Term(term) => Some(match term { TermOrVariable::Term(term) => Some(match term {
Term::NamedNode(term) => self.encode_named_node_for_insertion(term)?, Term::NamedNode(term) => self.encode_named_node_for_insertion(term)?,
Term::BlankNode(bnode) => self Term::BlankNode(bnode) => self
.write .storage
.encode_blank_node(bnodes.entry(bnode.clone()).or_default().as_ref()) .encode_blank_node(bnodes.entry(bnode.clone()).or_default().as_ref())?,
.map_err(to_eval_error)?,
Term::Literal(term) => self.encode_literal_for_insertion(term)?, Term::Literal(term) => self.encode_literal_for_insertion(term)?,
}), }),
TermOrVariable::Variable(v) => { TermOrVariable::Variable(v) => {
@ -501,26 +450,24 @@ where
&mut self, &mut self,
term: &NamedNode, term: &NamedNode,
) -> Result<EncodedTerm, EvaluationError> { ) -> Result<EncodedTerm, EvaluationError> {
self.write Ok(self
.encode_named_node(NamedNodeRef::new_unchecked(&term.iri)) .storage
.map_err(to_eval_error) .encode_named_node(NamedNodeRef::new_unchecked(&term.iri))?)
} }
fn encode_literal_for_insertion( fn encode_literal_for_insertion(
&mut self, &mut self,
term: &Literal, term: &Literal,
) -> Result<EncodedTerm, EvaluationError> { ) -> Result<EncodedTerm, EvaluationError> {
self.write Ok(self.storage.encode_literal(match term {
.encode_literal(match term { Literal::Simple { value } => LiteralRef::new_simple_literal(value),
Literal::Simple { value } => LiteralRef::new_simple_literal(value), Literal::LanguageTaggedString { value, language } => {
Literal::LanguageTaggedString { value, language } => { LiteralRef::new_language_tagged_literal_unchecked(value, language)
LiteralRef::new_language_tagged_literal_unchecked(value, language) }
} Literal::Typed { value, datatype } => {
Literal::Typed { value, datatype } => { LiteralRef::new_typed_literal(value, NamedNodeRef::new_unchecked(&datatype.iri))
LiteralRef::new_typed_literal(value, NamedNodeRef::new_unchecked(&datatype.iri)) }
} })?)
})
.map_err(to_eval_error)
} }
fn encode_quad_for_deletion( fn encode_quad_for_deletion(
@ -675,29 +622,23 @@ where
&self, &self,
term: &NamedNode, term: &NamedNode,
) -> Result<Option<EncodedTerm>, EvaluationError> { ) -> Result<Option<EncodedTerm>, EvaluationError> {
self.read Ok(self
.get_encoded_named_node(NamedNodeRef::new_unchecked(&term.iri)) .storage
.map_err(to_eval_error) .get_encoded_named_node(NamedNodeRef::new_unchecked(&term.iri))?)
} }
fn encode_literal_for_deletion( fn encode_literal_for_deletion(
&self, &self,
term: &Literal, term: &Literal,
) -> Result<Option<EncodedTerm>, EvaluationError> { ) -> Result<Option<EncodedTerm>, EvaluationError> {
self.read Ok(self.storage.get_encoded_literal(match term {
.get_encoded_literal(match term { Literal::Simple { value } => LiteralRef::new_simple_literal(value),
Literal::Simple { value } => LiteralRef::new_simple_literal(value), Literal::LanguageTaggedString { value, language } => {
Literal::LanguageTaggedString { value, language } => { LiteralRef::new_language_tagged_literal_unchecked(value, language)
LiteralRef::new_language_tagged_literal_unchecked(value, language) }
} Literal::Typed { value, datatype } => {
Literal::Typed { value, datatype } => { LiteralRef::new_typed_literal(value, NamedNodeRef::new_unchecked(&datatype.iri))
LiteralRef::new_typed_literal(value, NamedNodeRef::new_unchecked(&datatype.iri)) }
} })?)
})
.map_err(to_eval_error)
} }
} }
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::io::{DatasetFormat, DatasetSerializer, GraphFormat, GraphSerializer};
use crate::model::*; use crate::model::*;
use crate::store::numeric_encoder::*; use crate::store::numeric_encoder::*;
use crate::store::storage::StorageLike;
use oxiri::Iri; use oxiri::Iri;
use rio_api::parser::{QuadsParser, TriplesParser}; use rio_api::parser::{QuadsParser, TriplesParser};
use rio_turtle::{NQuadsParser, NTriplesParser, TriGParser, TurtleError, TurtleParser}; use rio_turtle::{NQuadsParser, NTriplesParser, TriGParser, TurtleError, TurtleParser};
@ -55,8 +56,8 @@ pub(crate) trait WritableEncodedStore: StrEncodingAware {
fn clear(&mut self) -> Result<(), Self::Error>; fn clear(&mut self) -> Result<(), Self::Error>;
} }
pub(crate) fn load_graph<S: WritableEncodedStore + StrContainer>( pub(crate) fn load_graph<S: StorageLike>(
store: &mut S, storage: &S,
reader: impl BufRead, reader: impl BufRead,
format: GraphFormat, format: GraphFormat,
to_graph_name: GraphNameRef<'_>, to_graph_name: GraphNameRef<'_>,
@ -69,19 +70,19 @@ pub(crate) fn load_graph<S: WritableEncodedStore + StrContainer>(
}; };
match format { match format {
GraphFormat::NTriples => { 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 => { 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 => { 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>( fn load_from_triple_parser<S: StorageLike, P: TriplesParser>(
store: &mut S, storage: &S,
mut parser: P, mut parser: P,
to_graph_name: GraphNameRef<'_>, to_graph_name: GraphNameRef<'_>,
) -> Result<(), StoreOrParseError<S::Error>> ) -> Result<(), StoreOrParseError<S::Error>>
@ -89,16 +90,14 @@ where
StoreOrParseError<S::Error>: From<P::Error>, StoreOrParseError<S::Error>: From<P::Error>,
{ {
let mut bnode_map = HashMap::default(); let mut bnode_map = HashMap::default();
let to_graph_name = store let to_graph_name = storage
.encode_graph_name(to_graph_name) .encode_graph_name(to_graph_name)
.map_err(StoreOrParseError::Store)?; .map_err(StoreOrParseError::Store)?;
parser.parse_all(&mut move |t| { parser.parse_all(&mut move |t| {
let quad = store let quad = storage
.encode_rio_triple_in_graph(t, to_graph_name, &mut bnode_map) .encode_rio_triple_in_graph(t, to_graph_name, &mut bnode_map)
.map_err(StoreOrParseError::Store)?; .map_err(StoreOrParseError::Store)?;
store storage.insert(&quad).map_err(StoreOrParseError::Store)?;
.insert_encoded(&quad)
.map_err(StoreOrParseError::Store)?;
Ok(()) Ok(())
}) })
} }

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

@ -1029,3 +1029,29 @@ impl<'a> StrContainer for StorageTransaction<'a> {
Ok(key) 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