refactored prepare_query

pull/11/head
Dustin Whitney 5 years ago
parent 2aa9114deb
commit 0e12edfdc9
  1. 16
      lib/src/repository.rs
  2. 96
      lib/src/sparql/eval.rs
  3. 21
      lib/src/sparql/mod.rs
  4. 7
      lib/src/sparql/plan.rs
  5. 12
      lib/src/store/mod.rs
  6. 9
      lib/tests/service_test_cases.rs
  7. 2
      lib/tests/sparql_test_cases.rs

@ -1,6 +1,7 @@
use crate::model::*; use crate::model::*;
use crate::sparql::{GraphPattern, PreparedQuery, QueryOptions}; use crate::sparql::{GraphPattern, PreparedQuery, QueryOptions};
use crate::{DatasetSyntax, GraphSyntax, Result}; use crate::{DatasetSyntax, GraphSyntax, Result};
use rio_api::iri::Iri;
use std::io::BufRead; use std::io::BufRead;
/// A `Repository` stores a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) /// A `Repository` stores a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset)
@ -81,7 +82,13 @@ pub trait RepositoryConnection: Clone {
/// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into())); /// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into()));
/// } /// }
/// ``` /// ```
fn prepare_query<'a>(&'a self, query: &str, options: &'a QueryOptions<'a>) -> Result<Self::PreparedQuery>; fn prepare_query<'a>(&'a self, query: &str, base_iri: Option<&'a str>) -> Result<Self::PreparedQuery>;
fn prepare_query_from_pattern<'a>(
&'a self,
graph_pattern: &'a GraphPattern,
) -> Result<Self::PreparedQuery>;
/// Retrieves quads with a filter on each quad component /// Retrieves quads with a filter on each quad component
/// ///
@ -112,13 +119,6 @@ pub trait RepositoryConnection: Clone {
where where
Self: 'a; Self: 'a;
fn prepare_query_from_pattern<'a>(
&'a self,
graph_pattern: &'a GraphPattern,
options: &'a QueryOptions<'a>
) -> Result<Self::PreparedQuery>;
/// Loads a graph file (i.e. triples) into the repository /// Loads a graph file (i.e. triples) into the repository
/// ///
/// Usage example: /// Usage example:

@ -41,16 +41,14 @@ type EncodedTuplesIterator<'a> = Box<dyn Iterator<Item = Result<EncodedTuple>> +
pub struct SimpleEvaluator<S: StoreConnection> { pub struct SimpleEvaluator<S: StoreConnection> {
dataset: DatasetView<S>, dataset: DatasetView<S>,
bnodes_map: Mutex<BTreeMap<u128, u128>>, bnodes_map: Mutex<BTreeMap<u128, u128>>,
base_iri: Option<Iri<String>>,
now: DateTime<FixedOffset>, now: DateTime<FixedOffset>,
} }
impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
pub fn new(dataset: DatasetView<S>, base_iri: Option<Iri<String>>) -> Self { pub fn new(dataset: DatasetView<S>) -> Self {
Self { Self {
dataset, dataset,
bnodes_map: Mutex::new(BTreeMap::default()), bnodes_map: Mutex::new(BTreeMap::default()),
base_iri,
now: Utc::now().with_timezone(&FixedOffset::east(0)), now: Utc::now().with_timezone(&FixedOffset::east(0)),
} }
} }
@ -113,6 +111,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
{ {
Ok(QueryResult::Graph(Box::new(DescribeIterator { Ok(QueryResult::Graph(Box::new(DescribeIterator {
eval: self, eval: self,
options,
iter: self.eval_plan(plan, vec![], options), iter: self.eval_plan(plan, vec![], options),
quads: Box::new(empty()), quads: Box::new(empty()),
}))) })))
@ -198,6 +197,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
get_pattern_value(&predicate, &tuple), get_pattern_value(&predicate, &tuple),
get_pattern_value(&object, &tuple), get_pattern_value(&object, &tuple),
get_pattern_value(&graph_name, &tuple), get_pattern_value(&graph_name, &tuple),
options.default_graph_as_union
); );
if subject.is_var() && subject == predicate { if subject.is_var() && subject == predicate {
iter = Box::new(iter.filter(|quad| match quad { iter = Box::new(iter.filter(|quad| match quad {
@ -271,7 +271,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
}; };
match (input_subject, input_object) { match (input_subject, input_object) {
(Some(input_subject), Some(input_object)) => Box::new( (Some(input_subject), Some(input_object)) => Box::new(
self.eval_path_from(path, input_subject, input_graph_name) self.eval_path_from(path, input_subject, input_graph_name, options)
.filter_map(move |o| match o { .filter_map(move |o| match o {
Ok(o) => { Ok(o) => {
if o == input_object { if o == input_object {
@ -285,7 +285,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
) )
as EncodedTuplesIterator<'_>, as EncodedTuplesIterator<'_>,
(Some(input_subject), None) => Box::new( (Some(input_subject), None) => Box::new(
self.eval_path_from(path, input_subject, input_graph_name) self.eval_path_from(path, input_subject, input_graph_name, options)
.map(move |o| { .map(move |o| {
let mut new_tuple = tuple.clone(); let mut new_tuple = tuple.clone();
put_pattern_value(&object, o?, &mut new_tuple); put_pattern_value(&object, o?, &mut new_tuple);
@ -293,7 +293,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
}), }),
), ),
(None, Some(input_object)) => Box::new( (None, Some(input_object)) => Box::new(
self.eval_path_to(path, input_object, input_graph_name) self.eval_path_to(path, input_object, input_graph_name, options)
.map(move |s| { .map(move |s| {
let mut new_tuple = tuple.clone(); let mut new_tuple = tuple.clone();
put_pattern_value(&subject, s?, &mut new_tuple); put_pattern_value(&subject, s?, &mut new_tuple);
@ -301,7 +301,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
}), }),
), ),
(None, None) => { (None, None) => {
Box::new(self.eval_open_path(path, input_graph_name).map(move |so| { Box::new(self.eval_open_path(path, input_graph_name, options).map(move |so| {
let mut new_tuple = tuple.clone(); let mut new_tuple = tuple.clone();
so.map(move |(s, o)| { so.map(move |(s, o)| {
put_pattern_value(&subject, s, &mut new_tuple); put_pattern_value(&subject, s, &mut new_tuple);
@ -580,6 +580,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
path: &'b PlanPropertyPath, path: &'b PlanPropertyPath,
start: EncodedTerm, start: EncodedTerm,
graph_name: EncodedTerm, graph_name: EncodedTerm,
options: &'b QueryOptions<'b>
) -> Box<dyn Iterator<Item = Result<EncodedTerm>> + 'b> ) -> Box<dyn Iterator<Item = Result<EncodedTerm>> + 'b>
where where
'a: 'b, 'a: 'b,
@ -587,33 +588,33 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
match path { match path {
PlanPropertyPath::PredicatePath(p) => Box::new( PlanPropertyPath::PredicatePath(p) => Box::new(
self.dataset self.dataset
.quads_for_pattern(Some(start), Some(*p), None, Some(graph_name)) .quads_for_pattern(Some(start), Some(*p), None, Some(graph_name), options.default_graph_as_union)
.map(|t| Ok(t?.object)), .map(|t| Ok(t?.object)),
), ),
PlanPropertyPath::InversePath(p) => self.eval_path_to(&p, start, graph_name), PlanPropertyPath::InversePath(p) => self.eval_path_to(&p, start, graph_name, options),
PlanPropertyPath::SequencePath(a, b) => Box::new( PlanPropertyPath::SequencePath(a, b) => Box::new(
self.eval_path_from(&a, start, graph_name) self.eval_path_from(&a, start, graph_name, options)
.flat_map_ok(move |middle| self.eval_path_from(&b, middle, graph_name)), .flat_map_ok(move |middle| self.eval_path_from(&b, middle, graph_name, options)),
), ),
PlanPropertyPath::AlternativePath(a, b) => Box::new( PlanPropertyPath::AlternativePath(a, b) => Box::new(
self.eval_path_from(&a, start, graph_name) self.eval_path_from(&a, start, graph_name, options)
.chain(self.eval_path_from(&b, start, graph_name)), .chain(self.eval_path_from(&b, start, graph_name, options)),
), ),
PlanPropertyPath::ZeroOrMorePath(p) => { PlanPropertyPath::ZeroOrMorePath(p) => {
Box::new(transitive_closure(Some(Ok(start)), move |e| { Box::new(transitive_closure(Some(Ok(start)), move |e| {
self.eval_path_from(p, e, graph_name) self.eval_path_from(p, e, graph_name, options)
})) }))
} }
PlanPropertyPath::OneOrMorePath(p) => Box::new(transitive_closure( PlanPropertyPath::OneOrMorePath(p) => Box::new(transitive_closure(
self.eval_path_from(p, start, graph_name), self.eval_path_from(p, start, graph_name, options),
move |e| self.eval_path_from(p, e, graph_name), move |e| self.eval_path_from(p, e, graph_name, options),
)), )),
PlanPropertyPath::ZeroOrOnePath(p) => Box::new(hash_deduplicate( PlanPropertyPath::ZeroOrOnePath(p) => Box::new(hash_deduplicate(
once(Ok(start)).chain(self.eval_path_from(&p, start, graph_name)), once(Ok(start)).chain(self.eval_path_from(&p, start, graph_name, options)),
)), )),
PlanPropertyPath::NegatedPropertySet(ps) => Box::new( PlanPropertyPath::NegatedPropertySet(ps) => Box::new(
self.dataset self.dataset
.quads_for_pattern(Some(start), None, None, Some(graph_name)) .quads_for_pattern(Some(start), None, None, Some(graph_name), options.default_graph_as_union)
.filter(move |t| match t { .filter(move |t| match t {
Ok(t) => !ps.contains(&t.predicate), Ok(t) => !ps.contains(&t.predicate),
Err(_) => true, Err(_) => true,
@ -628,6 +629,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
path: &'b PlanPropertyPath, path: &'b PlanPropertyPath,
end: EncodedTerm, end: EncodedTerm,
graph_name: EncodedTerm, graph_name: EncodedTerm,
options: &'a QueryOptions<'b>
) -> Box<dyn Iterator<Item = Result<EncodedTerm>> + 'b> ) -> Box<dyn Iterator<Item = Result<EncodedTerm>> + 'b>
where where
'a: 'b, 'a: 'b,
@ -635,33 +637,33 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
match path { match path {
PlanPropertyPath::PredicatePath(p) => Box::new( PlanPropertyPath::PredicatePath(p) => Box::new(
self.dataset self.dataset
.quads_for_pattern(None, Some(*p), Some(end), Some(graph_name)) .quads_for_pattern(None, Some(*p), Some(end), Some(graph_name), options.default_graph_as_union)
.map(|t| Ok(t?.subject)), .map(|t| Ok(t?.subject)),
), ),
PlanPropertyPath::InversePath(p) => self.eval_path_from(&p, end, graph_name), PlanPropertyPath::InversePath(p) => self.eval_path_from(&p, end, graph_name, options),
PlanPropertyPath::SequencePath(a, b) => Box::new( PlanPropertyPath::SequencePath(a, b) => Box::new(
self.eval_path_to(&b, end, graph_name) self.eval_path_to(&b, end, graph_name, options)
.flat_map_ok(move |middle| self.eval_path_to(&a, middle, graph_name)), .flat_map_ok(move |middle| self.eval_path_to(&a, middle, graph_name, options)),
), ),
PlanPropertyPath::AlternativePath(a, b) => Box::new( PlanPropertyPath::AlternativePath(a, b) => Box::new(
self.eval_path_to(&a, end, graph_name) self.eval_path_to(&a, end, graph_name, options)
.chain(self.eval_path_to(&b, end, graph_name)), .chain(self.eval_path_to(&b, end, graph_name, options)),
), ),
PlanPropertyPath::ZeroOrMorePath(p) => { PlanPropertyPath::ZeroOrMorePath(p) => {
Box::new(transitive_closure(Some(Ok(end)), move |e| { Box::new(transitive_closure(Some(Ok(end)), move |e| {
self.eval_path_to(p, e, graph_name) self.eval_path_to(p, e, graph_name, options)
})) }))
} }
PlanPropertyPath::OneOrMorePath(p) => Box::new(transitive_closure( PlanPropertyPath::OneOrMorePath(p) => Box::new(transitive_closure(
self.eval_path_to(p, end, graph_name), self.eval_path_to(p, end, graph_name, options),
move |e| self.eval_path_to(p, e, graph_name), move |e| self.eval_path_to(p, e, graph_name, options),
)), )),
PlanPropertyPath::ZeroOrOnePath(p) => Box::new(hash_deduplicate( PlanPropertyPath::ZeroOrOnePath(p) => Box::new(hash_deduplicate(
once(Ok(end)).chain(self.eval_path_to(&p, end, graph_name)), once(Ok(end)).chain(self.eval_path_to(&p, end, graph_name, options)),
)), )),
PlanPropertyPath::NegatedPropertySet(ps) => Box::new( PlanPropertyPath::NegatedPropertySet(ps) => Box::new(
self.dataset self.dataset
.quads_for_pattern(None, None, Some(end), Some(graph_name)) .quads_for_pattern(None, None, Some(end), Some(graph_name), options.default_graph_as_union)
.filter(move |t| match t { .filter(move |t| match t {
Ok(t) => !ps.contains(&t.predicate), Ok(t) => !ps.contains(&t.predicate),
Err(_) => true, Err(_) => true,
@ -675,6 +677,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
&'b self, &'b self,
path: &'b PlanPropertyPath, path: &'b PlanPropertyPath,
graph_name: EncodedTerm, graph_name: EncodedTerm,
options: &'b QueryOptions<'b>
) -> Box<dyn Iterator<Item = Result<(EncodedTerm, EncodedTerm)>> + 'b> ) -> Box<dyn Iterator<Item = Result<(EncodedTerm, EncodedTerm)>> + 'b>
where where
'a: 'b, 'a: 'b,
@ -682,45 +685,45 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
match path { match path {
PlanPropertyPath::PredicatePath(p) => Box::new( PlanPropertyPath::PredicatePath(p) => Box::new(
self.dataset self.dataset
.quads_for_pattern(None, Some(*p), None, Some(graph_name)) .quads_for_pattern(None, Some(*p), None, Some(graph_name), options.default_graph_as_union)
.map(|t| t.map(|t| (t.subject, t.object))), .map(|t| t.map(|t| (t.subject, t.object))),
), ),
PlanPropertyPath::InversePath(p) => Box::new( PlanPropertyPath::InversePath(p) => Box::new(
self.eval_open_path(&p, graph_name) self.eval_open_path(&p, graph_name, options)
.map(|t| t.map(|(s, o)| (o, s))), .map(|t| t.map(|(s, o)| (o, s))),
), ),
PlanPropertyPath::SequencePath(a, b) => Box::new( PlanPropertyPath::SequencePath(a, b) => Box::new(
self.eval_open_path(&a, graph_name) self.eval_open_path(&a, graph_name, options)
.flat_map_ok(move |(start, middle)| { .flat_map_ok(move |(start, middle)| {
self.eval_path_from(&b, middle, graph_name) self.eval_path_from(&b, middle, graph_name, options)
.map(move |end| Ok((start, end?))) .map(move |end| Ok((start, end?)))
}), }),
), ),
PlanPropertyPath::AlternativePath(a, b) => Box::new( PlanPropertyPath::AlternativePath(a, b) => Box::new(
self.eval_open_path(&a, graph_name) self.eval_open_path(&a, graph_name, options)
.chain(self.eval_open_path(&b, graph_name)), .chain(self.eval_open_path(&b, graph_name, options)),
), ),
PlanPropertyPath::ZeroOrMorePath(p) => Box::new(transitive_closure( PlanPropertyPath::ZeroOrMorePath(p) => Box::new(transitive_closure(
self.get_subject_or_object_identity_pairs(graph_name), //TODO: avoid to inject everything self.get_subject_or_object_identity_pairs(graph_name, options), //TODO: avoid to inject everything
move |(start, middle)| { move |(start, middle)| {
self.eval_path_from(p, middle, graph_name) self.eval_path_from(p, middle, graph_name, options)
.map(move |end| Ok((start, end?))) .map(move |end| Ok((start, end?)))
}, },
)), )),
PlanPropertyPath::OneOrMorePath(p) => Box::new(transitive_closure( PlanPropertyPath::OneOrMorePath(p) => Box::new(transitive_closure(
self.eval_open_path(p, graph_name), self.eval_open_path(p, graph_name, options),
move |(start, middle)| { move |(start, middle)| {
self.eval_path_from(p, middle, graph_name) self.eval_path_from(p, middle, graph_name, options)
.map(move |end| Ok((start, end?))) .map(move |end| Ok((start, end?)))
}, },
)), )),
PlanPropertyPath::ZeroOrOnePath(p) => Box::new(hash_deduplicate( PlanPropertyPath::ZeroOrOnePath(p) => Box::new(hash_deduplicate(
self.get_subject_or_object_identity_pairs(graph_name) self.get_subject_or_object_identity_pairs(graph_name, options)
.chain(self.eval_open_path(&p, graph_name)), .chain(self.eval_open_path(&p, graph_name, options)),
)), )),
PlanPropertyPath::NegatedPropertySet(ps) => Box::new( PlanPropertyPath::NegatedPropertySet(ps) => Box::new(
self.dataset self.dataset
.quads_for_pattern(None, None, None, Some(graph_name)) .quads_for_pattern(None, None, None, Some(graph_name), options.default_graph_as_union)
.filter(move |t| match t { .filter(move |t| match t {
Ok(t) => !ps.contains(&t.predicate), Ok(t) => !ps.contains(&t.predicate),
Err(_) => true, Err(_) => true,
@ -733,9 +736,10 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
fn get_subject_or_object_identity_pairs<'b>( fn get_subject_or_object_identity_pairs<'b>(
&'b self, &'b self,
graph_name: EncodedTerm, graph_name: EncodedTerm,
options: &'b QueryOptions<'b>
) -> impl Iterator<Item = Result<(EncodedTerm, EncodedTerm)>> + 'b { ) -> impl Iterator<Item = Result<(EncodedTerm, EncodedTerm)>> + 'b {
self.dataset self.dataset
.quads_for_pattern(None, None, None, Some(graph_name)) .quads_for_pattern(None, None, None, Some(graph_name), options.default_graph_as_union)
.flat_map_ok(|t| once(Ok(t.subject)).chain(once(Ok(t.object)))) .flat_map_ok(|t| once(Ok(t.subject)).chain(once(Ok(t.object))))
.map(|e| e.map(|e| (e, e))) .map(|e| e.map(|e| (e, e)))
} }
@ -929,7 +933,8 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
_ => None, _ => None,
}?; }?;
let iri = self.dataset.get_str(iri_id).ok()??; let iri = self.dataset.get_str(iri_id).ok()??;
if let Some(base_iri) = &self.base_iri { let base_iri = options.base_iri.map(|base_iri| Iri::parse(base_iri));
if let Some(Ok(base_iri)) = base_iri {
self.build_named_node(&base_iri.resolve(&iri).ok()?.into_inner()) self.build_named_node(&base_iri.resolve(&iri).ok()?.into_inner())
} else { } else {
Iri::parse(iri).ok()?; Iri::parse(iri).ok()?;
@ -2350,6 +2355,7 @@ fn decode_triple(
struct DescribeIterator<'a, S: StoreConnection + 'a> { struct DescribeIterator<'a, S: StoreConnection + 'a> {
eval: &'a SimpleEvaluator<S>, eval: &'a SimpleEvaluator<S>,
options: &'a QueryOptions<'a>,
iter: EncodedTuplesIterator<'a>, iter: EncodedTuplesIterator<'a>,
quads: Box<dyn Iterator<Item = Result<EncodedQuad>> + 'a>, quads: Box<dyn Iterator<Item = Result<EncodedQuad>> + 'a>,
} }
@ -2378,7 +2384,7 @@ impl<'a, S: StoreConnection + 'a> Iterator for DescribeIterator<'a, S> {
self.quads = self.quads =
self.eval self.eval
.dataset .dataset
.quads_for_pattern(Some(subject), None, None, None); .quads_for_pattern(Some(subject), None, None, None, self.options.default_graph_as_union);
} }
} }
} }

@ -19,7 +19,6 @@ use crate::sparql::plan_builder::PlanBuilder;
use crate::store::StoreConnection; use crate::store::StoreConnection;
use crate::Result; use crate::Result;
use std::fmt; use std::fmt;
use rio_api::iri::Iri;
pub use crate::sparql::algebra::GraphPattern; pub use crate::sparql::algebra::GraphPattern;
pub use crate::sparql::model::BindingsIterator; pub use crate::sparql::model::BindingsIterator;
@ -58,10 +57,10 @@ enum SimplePreparedQueryAction<S: StoreConnection> {
} }
impl<'a, S: StoreConnection + 'a> SimplePreparedQuery<S> { impl<'a, S: StoreConnection + 'a> SimplePreparedQuery<S> {
pub(crate) fn new(connection: S, query: &str, options: &'a QueryOptions<'a>) -> Result<Self> { pub(crate) fn new(connection: S, query: &str, base_iri: Option<&'a str>) -> Result<Self> {
let dataset = DatasetView::new(connection, options.default_graph_as_union); let dataset = DatasetView::new(connection);
//TODO avoid inserting terms in the Repository StringStore //TODO avoid inserting terms in the Repository StringStore
Ok(Self(match read_sparql_query(query, options.base_iri)? { Ok(Self(match read_sparql_query(query, base_iri)? {
QueryVariants::Select { QueryVariants::Select {
algebra, algebra,
dataset: _, dataset: _,
@ -71,7 +70,7 @@ impl<'a, S: StoreConnection + 'a> SimplePreparedQuery<S> {
SimplePreparedQueryAction::Select { SimplePreparedQueryAction::Select {
plan, plan,
variables, variables,
evaluator: SimpleEvaluator::new(dataset, base_iri), evaluator: SimpleEvaluator::new(dataset),
} }
} }
QueryVariants::Ask { QueryVariants::Ask {
@ -82,7 +81,7 @@ impl<'a, S: StoreConnection + 'a> SimplePreparedQuery<S> {
let (plan, _) = PlanBuilder::build(dataset.encoder(), &algebra)?; let (plan, _) = PlanBuilder::build(dataset.encoder(), &algebra)?;
SimplePreparedQueryAction::Ask { SimplePreparedQueryAction::Ask {
plan, plan,
evaluator: SimpleEvaluator::new(dataset, base_iri), evaluator: SimpleEvaluator::new(dataset),
} }
} }
QueryVariants::Construct { QueryVariants::Construct {
@ -99,7 +98,7 @@ impl<'a, S: StoreConnection + 'a> SimplePreparedQuery<S> {
&construct, &construct,
variables, variables,
)?, )?,
evaluator: SimpleEvaluator::new(dataset, base_iri), evaluator: SimpleEvaluator::new(dataset),
} }
} }
QueryVariants::Describe { QueryVariants::Describe {
@ -110,7 +109,7 @@ impl<'a, S: StoreConnection + 'a> SimplePreparedQuery<S> {
let (plan, _) = PlanBuilder::build(dataset.encoder(), &algebra)?; let (plan, _) = PlanBuilder::build(dataset.encoder(), &algebra)?;
SimplePreparedQueryAction::Describe { SimplePreparedQueryAction::Describe {
plan, plan,
evaluator: SimpleEvaluator::new(dataset, base_iri), evaluator: SimpleEvaluator::new(dataset),
} }
} }
})) }))
@ -119,15 +118,13 @@ impl<'a, S: StoreConnection + 'a> SimplePreparedQuery<S> {
pub(crate) fn new_from_pattern( pub(crate) fn new_from_pattern(
connection: S, connection: S,
pattern: &GraphPattern, pattern: &GraphPattern,
options: &'a QueryOptions<'a>
) -> Result<Self> { ) -> Result<Self> {
let dataset = DatasetView::new(connection, options.default_graph_as_union); let dataset = DatasetView::new(connection);
let iri = options.base_iri.map(|i| Iri::parse(i.to_string()).unwrap());
let (plan, variables) = PlanBuilder::build(dataset.encoder(), pattern)?; let (plan, variables) = PlanBuilder::build(dataset.encoder(), pattern)?;
Ok(Self(SimplePreparedQueryAction::Select { Ok(Self(SimplePreparedQueryAction::Select {
plan, plan,
variables, variables,
evaluator: SimpleEvaluator::new(dataset, iri), evaluator: SimpleEvaluator::new(dataset),
})) }))
} }
} }

@ -473,15 +473,13 @@ pub enum TripleTemplateValue {
pub struct DatasetView<S: StoreConnection> { pub struct DatasetView<S: StoreConnection> {
store: S, store: S,
extra: RefCell<MemoryStrStore>, extra: RefCell<MemoryStrStore>,
default_graph_as_union: bool,
} }
impl<S: StoreConnection> DatasetView<S> { impl<S: StoreConnection> DatasetView<S> {
pub fn new(store: S, default_graph_as_union: bool) -> Self { pub fn new(store: S) -> Self {
Self { Self {
store, store,
extra: RefCell::new(MemoryStrStore::default()), extra: RefCell::new(MemoryStrStore::default()),
default_graph_as_union,
} }
} }
@ -491,6 +489,7 @@ impl<S: StoreConnection> DatasetView<S> {
predicate: Option<EncodedTerm>, predicate: Option<EncodedTerm>,
object: Option<EncodedTerm>, object: Option<EncodedTerm>,
graph_name: Option<EncodedTerm>, graph_name: Option<EncodedTerm>,
default_graph_as_union: bool,
) -> Box<dyn Iterator<Item = Result<EncodedQuad>> + 'a> { ) -> Box<dyn Iterator<Item = Result<EncodedQuad>> + 'a> {
if graph_name == None { if graph_name == None {
Box::new( Box::new(
@ -501,7 +500,7 @@ impl<S: StoreConnection> DatasetView<S> {
Ok(quad) => quad.graph_name != ENCODED_DEFAULT_GRAPH, Ok(quad) => quad.graph_name != ENCODED_DEFAULT_GRAPH,
}), }),
) )
} else if graph_name == Some(ENCODED_DEFAULT_GRAPH) && self.default_graph_as_union { } else if graph_name == Some(ENCODED_DEFAULT_GRAPH) && default_graph_as_union {
Box::new( Box::new(
self.store self.store
.quads_for_pattern(subject, predicate, object, None) .quads_for_pattern(subject, predicate, object, None)

@ -11,9 +11,10 @@ pub use crate::store::memory::MemoryRepository;
pub use crate::store::rocksdb::RocksDbRepository; pub use crate::store::rocksdb::RocksDbRepository;
use crate::model::*; use crate::model::*;
use crate::sparql::{QueryOptions, SimplePreparedQuery}; use crate::sparql::{SimplePreparedQuery};
use crate::store::numeric_encoder::*; use crate::store::numeric_encoder::*;
use crate::{DatasetSyntax, GraphSyntax, RepositoryConnection, Result}; use crate::{DatasetSyntax, GraphSyntax, RepositoryConnection, Result};
use rio_api::iri::Iri;
use rio_api::parser::{QuadsParser, TriplesParser}; use rio_api::parser::{QuadsParser, TriplesParser};
use rio_turtle::{NQuadsParser, NTriplesParser, TriGParser, TurtleParser}; use rio_turtle::{NQuadsParser, NTriplesParser, TriGParser, TurtleParser};
use rio_xml::RdfXmlParser; use rio_xml::RdfXmlParser;
@ -72,8 +73,8 @@ impl<S: StoreConnection> From<S> for StoreRepositoryConnection<S> {
impl<S: StoreConnection> RepositoryConnection for StoreRepositoryConnection<S> { impl<S: StoreConnection> RepositoryConnection for StoreRepositoryConnection<S> {
type PreparedQuery = SimplePreparedQuery<S>; type PreparedQuery = SimplePreparedQuery<S>;
fn prepare_query<'a>(&self, query: &str, options: &'a QueryOptions<'a>) -> Result<SimplePreparedQuery<S>> { fn prepare_query<'a>(&self, query: &str, base_iri: Option<&'a str>) -> Result<SimplePreparedQuery<S>> {
SimplePreparedQuery::new(self.inner.clone(), query, options) //TODO: avoid clone SimplePreparedQuery::new(self.inner.clone(), query, base_iri) //TODO: avoid clone
} }
fn quads_for_pattern<'a>( fn quads_for_pattern<'a>(
@ -101,13 +102,10 @@ impl<S: StoreConnection> RepositoryConnection for StoreRepositoryConnection<S> {
fn prepare_query_from_pattern<'a>( fn prepare_query_from_pattern<'a>(
&'a self, &'a self,
pattern: &GraphPattern, pattern: &GraphPattern,
options: &'a QueryOptions<'a>
) -> Result<Self::PreparedQuery> { ) -> Result<Self::PreparedQuery> {
SimplePreparedQuery::new_from_pattern(self.inner.clone(), pattern, options) //TODO: avoid clone SimplePreparedQuery::new_from_pattern(self.inner.clone(), pattern) //TODO: avoid clone
} }
fn load_graph( fn load_graph(
&mut self, &mut self,
reader: impl BufRead, reader: impl BufRead,

@ -110,7 +110,7 @@ fn silent_service_test() {
#[derive(Clone,Copy)] #[derive(Clone,Copy)]
struct TwoServiceTest; struct TwoServiceTest;
impl ServiceHandler for TwoServiceTest { impl ServiceHandler for TwoServiceTest {
fn handle<'a>(&'a self, named_node: NamedNode) -> Option<(fn(GraphPattern) -> Result<BindingsIterator<'a>>)> { fn handle<'a>(&'a self, _named_node: NamedNode) -> Option<(fn(GraphPattern) -> Result<BindingsIterator<'a>>)> {
Some(TwoServiceTest::handle_service) Some(TwoServiceTest::handle_service)
} }
} }
@ -174,7 +174,7 @@ fn make_repository(reader: impl BufRead) -> Result<MemoryRepository> {
fn query_repository<'a>(repository: MemoryRepository, query: String, options: QueryOptions<'a>) -> Result<BindingsIterator<'a>> { fn query_repository<'a>(repository: MemoryRepository, query: String, options: QueryOptions<'a>) -> Result<BindingsIterator<'a>> {
let connection = repository.connection()?; let connection = repository.connection()?;
let prepared_query = connection.prepare_query(&query, &options)?; let prepared_query = connection.prepare_query(&query, None)?;
let result = prepared_query.exec(&options)?; let result = prepared_query.exec(&options)?;
match result { match result {
QueryResult::Bindings(iterator) => { QueryResult::Bindings(iterator) => {
@ -186,10 +186,9 @@ fn query_repository<'a>(repository: MemoryRepository, query: String, options: Qu
} }
} }
//fn pattern_repository<'a>(repository: MemoryRepository, pattern: GraphPattern, options: QueryOptions<'a>) -> Result<Vec<Vec<Option<Term>>>> {
fn pattern_repository<'a>(repository: MemoryRepository, pattern: GraphPattern, options: QueryOptions<'a>) -> Result<BindingsIterator<'a>> { fn pattern_repository<'a>(repository: MemoryRepository, pattern: GraphPattern, options: QueryOptions<'a>) -> Result<BindingsIterator<'a>> {
let connection = repository.connection()?; let connection = repository.connection()?;
let prepared_query = connection.prepare_query_from_pattern(&pattern, &options)?; let prepared_query = connection.prepare_query_from_pattern(&pattern)?;
let result = prepared_query.exec(&options)?; let result = prepared_query.exec(&options)?;
match result { match result {
QueryResult::Bindings(iterator) => { QueryResult::Bindings(iterator) => {
@ -201,13 +200,11 @@ fn pattern_repository<'a>(repository: MemoryRepository, pattern: GraphPattern, o
} }
} }
//fn do_query<'a>(reader: impl BufRead, query: String, options: QueryOptions<'a>) -> Result<Vec<Vec<Option<Term>>>> {
fn do_query<'a>(reader: impl BufRead, query: String, options: QueryOptions<'a>) -> Result<BindingsIterator<'a>> { fn do_query<'a>(reader: impl BufRead, query: String, options: QueryOptions<'a>) -> Result<BindingsIterator<'a>> {
let repository = make_repository(reader)?; let repository = make_repository(reader)?;
query_repository(repository, query, options) query_repository(repository, query, options)
} }
//fn do_pattern<'a>(reader: impl BufRead, pattern: GraphPattern, options: QueryOptions<'a>) -> Result<Vec<Vec<Option<Term>>>> {
fn do_pattern<'a>(reader: impl BufRead, pattern: GraphPattern, options: QueryOptions<'a>) -> Result<BindingsIterator<'a>> { fn do_pattern<'a>(reader: impl BufRead, pattern: GraphPattern, options: QueryOptions<'a>) -> Result<BindingsIterator<'a>> {
let repository = make_repository(reader)?; let repository = make_repository(reader)?;
pattern_repository(repository, pattern, options) pattern_repository(repository, pattern, options)

@ -158,7 +158,7 @@ fn sparql_w3c_query_evaluation_testsuite() -> Result<()> {
} }
match repository match repository
.connection()? .connection()?
.prepare_query(&read_file_to_string(&test.query)?, &QueryOptions::default().with_base_iri(&test.query)) .prepare_query(&read_file_to_string(&test.query)?, None)
{ {
Err(error) => Err(format_err!( Err(error) => Err(format_err!(
"Failure to parse query of {} with error: {}", "Failure to parse query of {} with error: {}",

Loading…
Cancel
Save