Runs cargo fmt

pull/14/head
Tpt 5 years ago
parent 033ee373d2
commit b4065e607c
  1. 6
      lib/src/repository.rs
  2. 295
      lib/src/sparql/eval.rs
  3. 16
      lib/src/sparql/mod.rs
  4. 4
      lib/src/sparql/plan.rs
  5. 2
      lib/src/sparql/plan_builder.rs
  6. 14
      lib/src/store/mod.rs
  7. 164
      lib/tests/service_test_cases.rs

@ -83,7 +83,11 @@ 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, base_iri: Option<&'a str>) -> Result<Self::PreparedQuery>; fn prepare_query<'a>(
&'a self,
query: &str,
base_iri: Option<&'a str>,
) -> Result<Self::PreparedQuery>;
/// This is similar to `prepare_query`, but useful if a SPARQL query has already been parsed, which is the case when building `ServiceHandler`s for federated queries with `SERVICE` clauses. For examples, look in the tests. /// This is similar to `prepare_query`, but useful if a SPARQL query has already been parsed, which is the case when building `ServiceHandler`s for federated queries with `SERVICE` clauses. For examples, look in the tests.
fn prepare_query_from_pattern<'a>( fn prepare_query_from_pattern<'a>(

@ -1,8 +1,8 @@
use crate::model::BlankNode; use crate::model::BlankNode;
use crate::model::Triple; use crate::model::Triple;
use crate::sparql::model::*; use crate::sparql::model::*;
use crate::sparql::QueryOptions;
use crate::sparql::plan::*; use crate::sparql::plan::*;
use crate::sparql::QueryOptions;
use crate::store::numeric_encoder::*; use crate::store::numeric_encoder::*;
use crate::store::StoreConnection; use crate::store::StoreConnection;
use crate::Result; use crate::Result;
@ -59,7 +59,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
&'b self, &'b self,
plan: &'b PlanNode, plan: &'b PlanNode,
variables: &[Variable], variables: &[Variable],
options: &'b QueryOptions<'b> options: &'b QueryOptions<'b>,
) -> Result<QueryResult<'b>> ) -> Result<QueryResult<'b>>
where where
'a: 'b, 'a: 'b,
@ -73,7 +73,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
pub fn evaluate_ask_plan<'b>( pub fn evaluate_ask_plan<'b>(
&'b self, &'b self,
plan: &'b PlanNode, plan: &'b PlanNode,
options: &'b QueryOptions<'b> options: &'b QueryOptions<'b>,
) -> Result<QueryResult<'b>> ) -> Result<QueryResult<'b>>
where where
'a: 'b, 'a: 'b,
@ -89,7 +89,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
&'b self, &'b self,
plan: &'b PlanNode, plan: &'b PlanNode,
construct: &'b [TripleTemplate], construct: &'b [TripleTemplate],
options: &'b QueryOptions<'b> options: &'b QueryOptions<'b>,
) -> Result<QueryResult<'b>> ) -> Result<QueryResult<'b>>
where where
'a: 'b, 'a: 'b,
@ -106,7 +106,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
pub fn evaluate_describe_plan<'b>( pub fn evaluate_describe_plan<'b>(
&'b self, &'b self,
plan: &'b PlanNode, plan: &'b PlanNode,
options: &'b QueryOptions<'b> options: &'b QueryOptions<'b>,
) -> Result<QueryResult<'b>> ) -> Result<QueryResult<'b>>
where where
'a: 'b, 'a: 'b,
@ -123,7 +123,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
&'b self, &'b self,
node: &'b PlanNode, node: &'b PlanNode,
from: EncodedTuple, from: EncodedTuple,
options: &'b QueryOptions<'b> options: &'b QueryOptions<'b>,
) -> EncodedTuplesIterator<'b> ) -> EncodedTuplesIterator<'b>
where where
'a: 'b, 'a: 'b,
@ -137,49 +137,53 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
service_name, service_name,
graph_pattern, graph_pattern,
.. ..
} => { } => match &options.service_handler {
match &options.service_handler { None => {
None => if *silent { if *silent {
return Box::new(empty()); return Box::new(empty());
} else { } else {
return Box::new(once(Err(format_err!( return Box::new(once(Err(format_err!(
"No handler was supplied to resolve the given service" "No handler was supplied to resolve the given service"
)))) as EncodedTuplesIterator<'_>; )))) as EncodedTuplesIterator<'_>;
}, }
}
Some(handler) => { Some(handler) => {
let pattern_option = match get_pattern_value(service_name, &[]) { let pattern_option = match get_pattern_value(service_name, &[]) {
None => if *silent { None => {
if *silent {
return Box::new(empty()); return Box::new(empty());
} else { } else {
return Box::new(once(Err(format_err!( return Box::new(once(Err(format_err!(
"The handler supplied was unable to evaluate the given service" "The handler supplied was unable to evaluate the given service"
)))) as EncodedTuplesIterator<'_>; ))))
}, as EncodedTuplesIterator<'_>;
Some(term) => { }
match self.dataset.decode_named_node(term) { }
Err(err) => if *silent { Some(term) => match self.dataset.decode_named_node(term) {
Err(err) => {
if *silent {
return Box::new(empty()); return Box::new(empty());
} else { } else {
return Box::new(once(Err(err))) as EncodedTuplesIterator<'_>; return Box::new(once(Err(err))) as EncodedTuplesIterator<'_>;
}, }
}
Ok(named_node) => { Ok(named_node) => {
println!("named_node: {:?}", named_node); println!("named_node: {:?}", named_node);
handler.handle(named_node) handler.handle(named_node)
} }
}
}, },
}; };
match pattern_option { match pattern_option {
None => if *silent { None => {
if *silent {
return Box::new(empty()); return Box::new(empty());
} else { } else {
return Box::new(once(Err(format_err!( return Box::new(once(Err(format_err!(
"The handler supplied was unable to produce any result set on the given service" "The handler supplied was unable to produce any result set on the given service"
)))) as EncodedTuplesIterator<'_>; )))) as EncodedTuplesIterator<'_>;
}, }
Some(pattern_fn) => { }
match pattern_fn(graph_pattern.clone()) { Some(pattern_fn) => match pattern_fn(graph_pattern.clone()) {
Ok(bindings) => { Ok(bindings) => {
let encoded = self.encode_bindings(variables, bindings); let encoded = self.encode_bindings(variables, bindings);
let collected = encoded.collect::<Vec<_>>(); let collected = encoded.collect::<Vec<_>>();
@ -188,19 +192,17 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
right_iter: Box::new(collected.into_iter()), right_iter: Box::new(collected.into_iter()),
buffered_results: vec![], buffered_results: vec![],
}) })
}, }
Err(err) => { Err(err) => {
if *silent { if *silent {
return Box::new(empty()); return Box::new(empty());
} else { } else {
return Box::new(once(Err(err))) as EncodedTuplesIterator<'_> return Box::new(once(Err(err))) as EncodedTuplesIterator<'_>;
}
} }
} }
}, },
} }
} }
}
}, },
PlanNode::QuadPatternJoin { PlanNode::QuadPatternJoin {
child, child,
@ -208,13 +210,15 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
predicate, predicate,
object, object,
graph_name, graph_name,
} => Box::new(self.eval_plan(&*child, from, options).flat_map_ok(move |tuple| { } => Box::new(
self.eval_plan(&*child, from, options)
.flat_map_ok(move |tuple| {
let mut iter = self.dataset.quads_for_pattern( let mut iter = self.dataset.quads_for_pattern(
get_pattern_value(&subject, &tuple), get_pattern_value(&subject, &tuple),
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 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 {
@ -268,14 +272,17 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
Ok(new_tuple) Ok(new_tuple)
})); }));
iter iter
})), }),
),
PlanNode::PathPatternJoin { PlanNode::PathPatternJoin {
child, child,
subject, subject,
path, path,
object, object,
graph_name, graph_name,
} => Box::new(self.eval_plan(&*child, from, options).flat_map_ok(move |tuple| { } => Box::new(
self.eval_plan(&*child, from, options)
.flat_map_ok(move |tuple| {
let input_subject = get_pattern_value(&subject, &tuple); let input_subject = get_pattern_value(&subject, &tuple);
let input_object = get_pattern_value(&object, &tuple); let input_object = get_pattern_value(&object, &tuple);
let input_graph_name = let input_graph_name =
@ -318,17 +325,20 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
}), }),
), ),
(None, None) => { (None, None) => {
Box::new(self.eval_open_path(path, input_graph_name, options).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);
put_pattern_value(&object, o, &mut new_tuple); put_pattern_value(&object, o, &mut new_tuple);
new_tuple new_tuple
}) })
})) },
))
} }
} }
})), }),
),
PlanNode::Join { left, right } => { PlanNode::Join { left, right } => {
//TODO: very dumb implementation //TODO: very dumb implementation
let mut errors = Vec::default(); let mut errors = Vec::default();
@ -456,7 +466,9 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
PlanNode::HashDeduplicate { child } => { PlanNode::HashDeduplicate { child } => {
Box::new(hash_deduplicate(self.eval_plan(&*child, from, options))) Box::new(hash_deduplicate(self.eval_plan(&*child, from, options)))
} }
PlanNode::Skip { child, count } => Box::new(self.eval_plan(&*child, from, options).skip(*count)), PlanNode::Skip { child, count } => {
Box::new(self.eval_plan(&*child, from, options).skip(*count))
}
PlanNode::Limit { child, count } => { PlanNode::Limit { child, count } => {
Box::new(self.eval_plan(&*child, from, options).take(*count)) Box::new(self.eval_plan(&*child, from, options).take(*count))
} }
@ -513,12 +525,9 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
}); });
for (i, accumulator) in key_accumulators.iter_mut().enumerate() { for (i, accumulator) in key_accumulators.iter_mut().enumerate() {
let (aggregate, _) = &aggregates[i]; let (aggregate, _) = &aggregates[i];
accumulator.add( accumulator.add(aggregate.parameter.as_ref().and_then(|parameter| {
aggregate self.eval_expression(&parameter, &tuple, options)
.parameter }));
.as_ref()
.and_then(|parameter| self.eval_expression(&parameter, &tuple, options)),
);
} }
}); });
if accumulators_for_group.is_empty() { if accumulators_for_group.is_empty() {
@ -597,7 +606,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> options: &'b QueryOptions<'b>,
) -> Box<dyn Iterator<Item = Result<EncodedTerm>> + 'b> ) -> Box<dyn Iterator<Item = Result<EncodedTerm>> + 'b>
where where
'a: 'b, 'a: 'b,
@ -605,13 +614,21 @@ 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), options.default_graph_as_union) .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, options), 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, options) self.eval_path_from(&a, start, graph_name, options)
.flat_map_ok(move |middle| self.eval_path_from(&b, middle, graph_name, options)), .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, options) self.eval_path_from(&a, start, graph_name, options)
@ -631,7 +648,13 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
)), )),
PlanPropertyPath::NegatedPropertySet(ps) => Box::new( PlanPropertyPath::NegatedPropertySet(ps) => Box::new(
self.dataset self.dataset
.quads_for_pattern(Some(start), None, None, Some(graph_name), options.default_graph_as_union) .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,
@ -646,7 +669,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> options: &'a QueryOptions<'b>,
) -> Box<dyn Iterator<Item = Result<EncodedTerm>> + 'b> ) -> Box<dyn Iterator<Item = Result<EncodedTerm>> + 'b>
where where
'a: 'b, 'a: 'b,
@ -654,7 +677,13 @@ 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), options.default_graph_as_union) .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, options), PlanPropertyPath::InversePath(p) => self.eval_path_from(&p, end, graph_name, options),
@ -680,7 +709,13 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
)), )),
PlanPropertyPath::NegatedPropertySet(ps) => Box::new( PlanPropertyPath::NegatedPropertySet(ps) => Box::new(
self.dataset self.dataset
.quads_for_pattern(None, None, Some(end), Some(graph_name), options.default_graph_as_union) .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,
@ -694,7 +729,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> 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,
@ -702,7 +737,13 @@ 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), options.default_graph_as_union) .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(
@ -740,7 +781,13 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
)), )),
PlanPropertyPath::NegatedPropertySet(ps) => Box::new( PlanPropertyPath::NegatedPropertySet(ps) => Box::new(
self.dataset self.dataset
.quads_for_pattern(None, None, None, Some(graph_name), options.default_graph_as_union) .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,
@ -753,10 +800,16 @@ 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> 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), options.default_graph_as_union) .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)))
} }
@ -765,21 +818,29 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
&'b self, &'b self,
expression: &PlanExpression, expression: &PlanExpression,
tuple: &[Option<EncodedTerm>], tuple: &[Option<EncodedTerm>],
options: &QueryOptions<'b> options: &QueryOptions<'b>,
) -> Option<EncodedTerm> { ) -> Option<EncodedTerm> {
match expression { match expression {
PlanExpression::Constant(t) => Some(*t), PlanExpression::Constant(t) => Some(*t),
PlanExpression::Variable(v) => get_tuple_value(*v, tuple), PlanExpression::Variable(v) => get_tuple_value(*v, tuple),
PlanExpression::Exists(node) => { PlanExpression::Exists(node) => Some(
Some(self.eval_plan(node, tuple.to_vec(), options).next().is_some().into()) self.eval_plan(node, tuple.to_vec(), options)
} .next()
.is_some()
.into(),
),
PlanExpression::Or(a, b) => { PlanExpression::Or(a, b) => {
match self.eval_expression(a, tuple, options).and_then(|v| self.to_bool(v)) { match self
.eval_expression(a, tuple, options)
.and_then(|v| self.to_bool(v))
{
Some(true) => Some(true.into()), Some(true) => Some(true.into()),
Some(false) => self.eval_expression(b, tuple, options), Some(false) => self.eval_expression(b, tuple, options),
None => { None => {
if Some(true) if Some(true)
== self.eval_expression(b, tuple, options).and_then(|v| self.to_bool(v)) == self
.eval_expression(b, tuple, options)
.and_then(|v| self.to_bool(v))
{ {
Some(true.into()) Some(true.into())
} else { } else {
@ -795,7 +856,11 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
Some(true) => self.eval_expression(b, tuple, options), Some(true) => self.eval_expression(b, tuple, options),
Some(false) => Some(false.into()), Some(false) => Some(false.into()),
None => { None => {
if Some(false) == self.eval_expression(b, tuple, options).and_then(|v| self.to_bool(v)) { if Some(false)
== self
.eval_expression(b, tuple, options)
.and_then(|v| self.to_bool(v))
{
Some(false.into()) Some(false.into())
} else { } else {
None None
@ -864,32 +929,40 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
Some(false.into()) Some(false.into())
} }
} }
PlanExpression::Add(a, b) => Some(match self.parse_numeric_operands(a, b, tuple, options)? { PlanExpression::Add(a, b) => {
Some(match self.parse_numeric_operands(a, b, tuple, options)? {
NumericBinaryOperands::Float(v1, v2) => (v1 + v2).into(), NumericBinaryOperands::Float(v1, v2) => (v1 + v2).into(),
NumericBinaryOperands::Double(v1, v2) => (v1 + v2).into(), NumericBinaryOperands::Double(v1, v2) => (v1 + v2).into(),
NumericBinaryOperands::Integer(v1, v2) => v1.checked_add(v2)?.into(), NumericBinaryOperands::Integer(v1, v2) => v1.checked_add(v2)?.into(),
NumericBinaryOperands::Decimal(v1, v2) => v1.checked_add(v2)?.into(), NumericBinaryOperands::Decimal(v1, v2) => v1.checked_add(v2)?.into(),
}), })
PlanExpression::Sub(a, b) => Some(match self.parse_numeric_operands(a, b, tuple, options)? { }
PlanExpression::Sub(a, b) => {
Some(match self.parse_numeric_operands(a, b, tuple, options)? {
NumericBinaryOperands::Float(v1, v2) => (v1 - v2).into(), NumericBinaryOperands::Float(v1, v2) => (v1 - v2).into(),
NumericBinaryOperands::Double(v1, v2) => (v1 - v2).into(), NumericBinaryOperands::Double(v1, v2) => (v1 - v2).into(),
NumericBinaryOperands::Integer(v1, v2) => v1.checked_sub(v2)?.into(), NumericBinaryOperands::Integer(v1, v2) => v1.checked_sub(v2)?.into(),
NumericBinaryOperands::Decimal(v1, v2) => v1.checked_sub(v2)?.into(), NumericBinaryOperands::Decimal(v1, v2) => v1.checked_sub(v2)?.into(),
}), })
PlanExpression::Mul(a, b) => Some(match self.parse_numeric_operands(a, b, tuple, options)? { }
PlanExpression::Mul(a, b) => {
Some(match self.parse_numeric_operands(a, b, tuple, options)? {
NumericBinaryOperands::Float(v1, v2) => (v1 * v2).into(), NumericBinaryOperands::Float(v1, v2) => (v1 * v2).into(),
NumericBinaryOperands::Double(v1, v2) => (v1 * v2).into(), NumericBinaryOperands::Double(v1, v2) => (v1 * v2).into(),
NumericBinaryOperands::Integer(v1, v2) => v1.checked_mul(v2)?.into(), NumericBinaryOperands::Integer(v1, v2) => v1.checked_mul(v2)?.into(),
NumericBinaryOperands::Decimal(v1, v2) => v1.checked_mul(v2)?.into(), NumericBinaryOperands::Decimal(v1, v2) => v1.checked_mul(v2)?.into(),
}), })
PlanExpression::Div(a, b) => Some(match self.parse_numeric_operands(a, b, tuple, options)? { }
PlanExpression::Div(a, b) => {
Some(match self.parse_numeric_operands(a, b, tuple, options)? {
NumericBinaryOperands::Float(v1, v2) => (v1 / v2).into(), NumericBinaryOperands::Float(v1, v2) => (v1 / v2).into(),
NumericBinaryOperands::Double(v1, v2) => (v1 / v2).into(), NumericBinaryOperands::Double(v1, v2) => (v1 / v2).into(),
NumericBinaryOperands::Integer(v1, v2) => Decimal::from_i128(v1)? NumericBinaryOperands::Integer(v1, v2) => Decimal::from_i128(v1)?
.checked_div(Decimal::from_i128(v2)?)? .checked_div(Decimal::from_i128(v2)?)?
.into(), .into(),
NumericBinaryOperands::Decimal(v1, v2) => v1.checked_div(v2)?.into(), NumericBinaryOperands::Decimal(v1, v2) => v1.checked_div(v2)?.into(),
}), })
}
PlanExpression::UnaryPlus(e) => match self.eval_expression(e, tuple, options)? { PlanExpression::UnaryPlus(e) => match self.eval_expression(e, tuple, options)? {
EncodedTerm::FloatLiteral(value) => Some((*value).into()), EncodedTerm::FloatLiteral(value) => Some((*value).into()),
EncodedTerm::DoubleLiteral(value) => Some((*value).into()), EncodedTerm::DoubleLiteral(value) => Some((*value).into()),
@ -950,7 +1023,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()??;
let base_iri = options.base_iri let base_iri = options
.base_iri
.map(|base_iri| Iri::parse(base_iri.to_string())) .map(|base_iri| Iri::parse(base_iri.to_string()))
.or(self.base_iri.as_ref().map(|iri| Ok(iri.clone()))); .or(self.base_iri.as_ref().map(|iri| Ok(iri.clone())));
if let Some(Ok(base_iri)) = base_iri { if let Some(Ok(base_iri)) = base_iri {
@ -1043,7 +1117,9 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
return None; return None;
}; };
let length: Option<usize> = if let Some(length) = length { let length: Option<usize> = if let Some(length) = length {
if let EncodedTerm::IntegerLiteral(v) = self.eval_expression(length, tuple, options)? { if let EncodedTerm::IntegerLiteral(v) =
self.eval_expression(length, tuple, options)?
{
Some(v.try_into().ok()?) Some(v.try_into().ok()?)
} else { } else {
return None; return None;
@ -1313,14 +1389,18 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
} }
PlanExpression::StrLang(lexical_form, lang_tag) => { PlanExpression::StrLang(lexical_form, lang_tag) => {
Some(EncodedTerm::LangStringLiteral { Some(EncodedTerm::LangStringLiteral {
value_id: self value_id: self.to_simple_string_id(self.eval_expression(
.to_simple_string_id(self.eval_expression(lexical_form, tuple, options)?)?, lexical_form,
tuple,
options,
)?)?,
language_id: self language_id: self
.to_simple_string_id(self.eval_expression(lang_tag, tuple, options)?)?, .to_simple_string_id(self.eval_expression(lang_tag, tuple, options)?)?,
}) })
} }
PlanExpression::StrDT(lexical_form, datatype) => { PlanExpression::StrDT(lexical_form, datatype) => {
let value = self.to_simple_string(self.eval_expression(lexical_form, tuple, options)?)?; let value =
self.to_simple_string(self.eval_expression(lexical_form, tuple, options)?)?;
let datatype = if let EncodedTerm::NamedNode { iri_id } = let datatype = if let EncodedTerm::NamedNode { iri_id } =
self.eval_expression(datatype, tuple, options)? self.eval_expression(datatype, tuple, options)?
{ {
@ -1336,15 +1416,21 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
}) })
.ok() .ok()
} }
PlanExpression::SameTerm(a, b) => { PlanExpression::SameTerm(a, b) => Some(
Some((self.eval_expression(a, tuple, options)? == self.eval_expression(b, tuple, options)?).into()) (self.eval_expression(a, tuple, options)?
} == self.eval_expression(b, tuple, options)?)
PlanExpression::IsIRI(e) => { .into(),
Some(self.eval_expression(e, tuple, options)?.is_named_node().into()) ),
} PlanExpression::IsIRI(e) => Some(
PlanExpression::IsBlank(e) => { self.eval_expression(e, tuple, options)?
Some(self.eval_expression(e, tuple, options)?.is_blank_node().into()) .is_named_node()
} .into(),
),
PlanExpression::IsBlank(e) => Some(
self.eval_expression(e, tuple, options)?
.is_blank_node()
.into(),
),
PlanExpression::IsLiteral(e) => { PlanExpression::IsLiteral(e) => {
Some(self.eval_expression(e, tuple, options)?.is_literal().into()) Some(self.eval_expression(e, tuple, options)?.is_literal().into())
} }
@ -1630,7 +1716,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
e1: &PlanExpression, e1: &PlanExpression,
e2: &PlanExpression, e2: &PlanExpression,
tuple: &[Option<EncodedTerm>], tuple: &[Option<EncodedTerm>],
options: &QueryOptions<'b> options: &QueryOptions<'b>,
) -> Option<NumericBinaryOperands> { ) -> Option<NumericBinaryOperands> {
NumericBinaryOperands::new( NumericBinaryOperands::new(
self.eval_expression(&e1, tuple, options)?, self.eval_expression(&e1, tuple, options)?,
@ -1687,7 +1773,12 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
Some(term) => { Some(term) => {
if let Ok(encoded) = encoder.encode_term(&term) { if let Ok(encoded) = encoder.encode_term(&term) {
let variable = binding_variables[i].clone(); let variable = binding_variables[i].clone();
put_variable_value(&variable, &combined_variables, encoded, &mut encoded_terms) put_variable_value(
&variable,
&combined_variables,
encoded,
&mut encoded_terms,
)
} }
} }
} }
@ -1696,7 +1787,6 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
})) }))
} }
#[allow(clippy::float_cmp)] #[allow(clippy::float_cmp)]
fn equals(&self, a: EncodedTerm, b: EncodedTerm) -> Option<bool> { fn equals(&self, a: EncodedTerm, b: EncodedTerm) -> Option<bool> {
match a { match a {
@ -1814,7 +1904,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
tuple_a: &[Option<EncodedTerm>], tuple_a: &[Option<EncodedTerm>],
tuple_b: &[Option<EncodedTerm>], tuple_b: &[Option<EncodedTerm>],
expression: &PlanExpression, expression: &PlanExpression,
options: &QueryOptions<'b> options: &QueryOptions<'b>,
) -> Ordering { ) -> Ordering {
self.cmp_terms( self.cmp_terms(
self.eval_expression(expression, tuple_a, options), self.eval_expression(expression, tuple_a, options),
@ -1933,7 +2023,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
&'b self, &'b self,
arg: &PlanExpression, arg: &PlanExpression,
tuple: &[Option<EncodedTerm>], tuple: &[Option<EncodedTerm>],
options: &QueryOptions<'b> options: &QueryOptions<'b>,
) -> Option<EncodedTerm> { ) -> Option<EncodedTerm> {
let input = self.to_simple_string(self.eval_expression(arg, tuple, options)?)?; let input = self.to_simple_string(self.eval_expression(arg, tuple, options)?)?;
let hash = hex::encode(H::new().chain(&input as &str).result()); let hash = hex::encode(H::new().chain(&input as &str).result());
@ -2071,7 +2161,12 @@ fn put_pattern_value(selector: &PatternValue, value: EncodedTerm, tuple: &mut En
} }
} }
fn put_variable_value(selector: &Variable, variables: &[Variable], value: EncodedTerm, tuple: &mut EncodedTuple) { fn put_variable_value(
selector: &Variable,
variables: &[Variable],
value: EncodedTerm,
tuple: &mut EncodedTuple,
) {
for (i, v) in variables.iter().enumerate() { for (i, v) in variables.iter().enumerate() {
if selector == v { if selector == v {
put_value(i, value, tuple); put_value(i, value, tuple);
@ -2080,7 +2175,6 @@ fn put_variable_value(selector: &Variable, variables: &[Variable], value: Encode
} }
} }
fn put_value(position: usize, value: EncodedTerm, tuple: &mut EncodedTuple) { fn put_value(position: usize, value: EncodedTerm, tuple: &mut EncodedTuple) {
if position < tuple.len() { if position < tuple.len() {
tuple[position] = Some(value) tuple[position] = Some(value)
@ -2226,7 +2320,9 @@ impl<'a, S: StoreConnection> Iterator for LeftJoinIterator<'a, S> {
} }
match self.left_iter.next()? { match self.left_iter.next()? {
Ok(left_tuple) => { Ok(left_tuple) => {
self.current_right = self.eval.eval_plan(self.right_plan, left_tuple.clone(), self.options); self.current_right =
self.eval
.eval_plan(self.right_plan, left_tuple.clone(), self.options);
if let Some(right_tuple) = self.current_right.next() { if let Some(right_tuple) = self.current_right.next() {
Some(right_tuple) Some(right_tuple)
} else { } else {
@ -2294,9 +2390,11 @@ impl<'a, S: StoreConnection> Iterator for UnionIterator<'a, S> {
if self.current_plan >= self.plans.len() { if self.current_plan >= self.plans.len() {
return None; return None;
} }
self.current_iterator = self self.current_iterator = self.eval.eval_plan(
.eval &self.plans[self.current_plan],
.eval_plan(&self.plans[self.current_plan], self.input.clone(), self.options); self.input.clone(),
self.options,
);
self.current_plan += 1; self.current_plan += 1;
} }
} }
@ -2401,10 +2499,13 @@ impl<'a, S: StoreConnection + 'a> Iterator for DescribeIterator<'a, S> {
}; };
for subject in tuple { for subject in tuple {
if let Some(subject) = subject { if let Some(subject) = subject {
self.quads = self.quads = self.eval.dataset.quads_for_pattern(
self.eval Some(subject),
.dataset None,
.quads_for_pattern(Some(subject), None, None, None, self.options.default_graph_as_union); None,
None,
self.options.default_graph_as_union,
);
} }
} }
} }

@ -121,27 +121,24 @@ 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,
base_iri: Option<&'a str> base_iri: Option<&'a str>,
) -> Result<Self> { ) -> Result<Self> {
let dataset = DatasetView::new(connection); let dataset = DatasetView::new(connection);
let (plan, variables) = PlanBuilder::build(dataset.encoder(), pattern)?; let (plan, variables) = PlanBuilder::build(dataset.encoder(), pattern)?;
let base_iri = base_iri.map(|str_iri| Iri::parse(str_iri.to_string())); let base_iri = base_iri.map(|str_iri| Iri::parse(str_iri.to_string()));
match base_iri { match base_iri {
Some(Err(_)) => Err(format_err!("Failed to parse base_iri")), Some(Err(_)) => Err(format_err!("Failed to parse base_iri")),
Some(Ok(base_iri)) => Some(Ok(base_iri)) => Ok(Self(SimplePreparedQueryAction::Select {
Ok(Self(SimplePreparedQueryAction::Select {
plan, plan,
variables, variables,
evaluator: SimpleEvaluator::new(dataset, Some(base_iri)), evaluator: SimpleEvaluator::new(dataset, Some(base_iri)),
})), })),
None => None => Ok(Self(SimplePreparedQueryAction::Select {
Ok(Self(SimplePreparedQueryAction::Select {
plan, plan,
variables, variables,
evaluator: SimpleEvaluator::new(dataset, None), evaluator: SimpleEvaluator::new(dataset, None),
})) })),
} }
} }
} }
@ -169,7 +166,10 @@ impl<S: StoreConnection> PreparedQuery for SimplePreparedQuery<S> {
} }
pub trait ServiceHandler { pub trait ServiceHandler {
fn handle<'a>(&'a self, node: NamedNode) -> Option<(fn(GraphPattern) -> Result<BindingsIterator<'a>>)>; fn handle<'a>(
&'a self,
node: NamedNode,
) -> Option<(fn(GraphPattern) -> Result<BindingsIterator<'a>>)>;
} }
/// Options for SPARQL query parsing and evaluation like the query base IRI /// Options for SPARQL query parsing and evaluation like the query base IRI

@ -1,6 +1,6 @@
use crate::sparql::GraphPattern;
use crate::sparql::model::Variable;
use crate::sparql::eval::StringOrStoreString; use crate::sparql::eval::StringOrStoreString;
use crate::sparql::model::Variable;
use crate::sparql::GraphPattern;
use crate::store::numeric_encoder::{ use crate::store::numeric_encoder::{
EncodedQuad, EncodedTerm, Encoder, MemoryStrStore, StrContainer, StrLookup, EncodedQuad, EncodedTerm, Encoder, MemoryStrStore, StrContainer, StrLookup,
ENCODED_DEFAULT_GRAPH, ENCODED_DEFAULT_GRAPH,

@ -113,7 +113,7 @@ impl<E: Encoder> PlanBuilder<E> {
graph_pattern, graph_pattern,
silent: *s, silent: *s,
} }
}, }
GraphPattern::AggregateJoin(GroupPattern(key, p), aggregates) => { GraphPattern::AggregateJoin(GroupPattern(key, p), aggregates) => {
let mut inner_variables = key.clone(); let mut inner_variables = key.clone();
let inner_graph_name = let inner_graph_name =

@ -11,7 +11,7 @@ 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::{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::parser::{QuadsParser, TriplesParser}; use rio_api::parser::{QuadsParser, TriplesParser};
@ -72,7 +72,11 @@ 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, base_iri: Option<&'a str>) -> Result<SimplePreparedQuery<S>> { fn prepare_query<'a>(
&self,
query: &str,
base_iri: Option<&'a str>,
) -> Result<SimplePreparedQuery<S>> {
SimplePreparedQuery::new(self.inner.clone(), query, base_iri) //TODO: avoid clone SimplePreparedQuery::new(self.inner.clone(), query, base_iri) //TODO: avoid clone
} }
@ -97,13 +101,13 @@ 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,
base_iri: Option<&'a str> base_iri: Option<&'a str>,
) -> Result<Self::PreparedQuery> { ) -> Result<Self::PreparedQuery> {
SimplePreparedQuery::new_from_pattern(self.inner.clone(), pattern, base_iri) //TODO: avoid clone SimplePreparedQuery::new_from_pattern(self.inner.clone(), pattern, base_iri)
//TODO: avoid clone
} }
fn load_graph( fn load_graph(

@ -1,19 +1,23 @@
use rudf::model::*;
use rudf::{GraphSyntax, Repository, RepositoryConnection, MemoryRepository, Result};
use rudf::sparql::{BindingsIterator, GraphPattern, PreparedQuery, QueryOptions, QueryResult, ServiceHandler};
use failure::format_err; use failure::format_err;
use rudf::model::*;
use rudf::sparql::{
BindingsIterator, GraphPattern, PreparedQuery, QueryOptions, QueryResult, ServiceHandler,
};
use rudf::{GraphSyntax, MemoryRepository, Repository, RepositoryConnection, Result};
use std::io::BufRead; use std::io::BufRead;
#[test] #[test]
fn simple_service_test() { fn simple_service_test() {
struct TestServiceHandler; struct TestServiceHandler;
impl ServiceHandler for TestServiceHandler { impl ServiceHandler for TestServiceHandler {
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>>)> {
fn pattern_handler<'a>(graph_pattern: GraphPattern) -> Result<BindingsIterator<'a>> { fn pattern_handler<'a>(graph_pattern: GraphPattern) -> Result<BindingsIterator<'a>> {
let triples = b"<http://example.com/s> <http://example.com/p> <http://example.com/o> .".as_ref(); let triples =
b"<http://example.com/s> <http://example.com/p> <http://example.com/o> ."
.as_ref();
do_pattern(triples, graph_pattern, QueryOptions::default()) do_pattern(triples, graph_pattern, QueryOptions::default())
}; };
Some(pattern_handler) Some(pattern_handler)
@ -28,43 +32,51 @@ fn simple_service_test() {
{ ?s ?p ?o { ?s ?p ?o
} }
} }
"#.to_string(); "#
.to_string();
let options = QueryOptions::default().with_service_handler(Box::new(TestServiceHandler)); let options = QueryOptions::default().with_service_handler(Box::new(TestServiceHandler));
let results = do_query(b"".as_ref(), query, options).unwrap(); let results = do_query(b"".as_ref(), query, options).unwrap();
let collected = results.into_values_iter().map(move |b| b.unwrap()).collect::<Vec<_>>(); let collected = results
let solution = vec![ .into_values_iter()
vec![ Some(ex(String::from("s"))), Some(ex(String::from("p"))), Some(ex(String::from("o"))) ], .map(move |b| b.unwrap())
]; .collect::<Vec<_>>();
let solution = vec![vec![
Some(ex(String::from("s"))),
Some(ex(String::from("p"))),
Some(ex(String::from("o"))),
]];
assert_eq!(collected, solution); assert_eq!(collected, solution);
} }
#[test] #[test]
fn two_service_test() { fn two_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>>)> {
let service1 = NamedNode::parse("http://service1.org").unwrap(); let service1 = NamedNode::parse("http://service1.org").unwrap();
let service2 = NamedNode::parse("http://service2.org").unwrap(); let service2 = NamedNode::parse("http://service2.org").unwrap();
if named_node == service1 { Some(TwoServiceTest::handle_service1) } if named_node == service1 {
else if named_node == service2 { Some(TwoServiceTest::handle_service2) } Some(TwoServiceTest::handle_service1)
else { None } } else if named_node == service2 {
Some(TwoServiceTest::handle_service2)
} else {
None
}
} }
} }
impl TwoServiceTest { impl TwoServiceTest {
fn handle_service1<'a>(graph_pattern: GraphPattern) -> Result<BindingsIterator<'a>> { fn handle_service1<'a>(graph_pattern: GraphPattern) -> Result<BindingsIterator<'a>> {
let triples = br#" let triples = br#"
<http://example.com/bob> <http://xmlns.com/foaf/0.1/name> "Bob" . <http://example.com/bob> <http://xmlns.com/foaf/0.1/name> "Bob" .
<http://example.com/alice> <http://xmlns.com/foaf/0.1/name> "Alice" . <http://example.com/alice> <http://xmlns.com/foaf/0.1/name> "Alice" .
"#.as_ref(); "#
.as_ref();
do_pattern(triples, graph_pattern, QueryOptions::default()) do_pattern(triples, graph_pattern, QueryOptions::default())
} }
@ -72,10 +84,10 @@ fn two_service_test() {
let triples = br#" let triples = br#"
<http://example.com/bob> <http://xmlns.com/foaf/0.1/mbox> <mailto:bob@example.com> . <http://example.com/bob> <http://xmlns.com/foaf/0.1/mbox> <mailto:bob@example.com> .
<http://example.com/alice> <http://xmlns.com/foaf/0.1/mbox> <mailto:alice@example.com> . <http://example.com/alice> <http://xmlns.com/foaf/0.1/mbox> <mailto:alice@example.com> .
"#.as_ref(); "#
.as_ref();
do_pattern(triples, graph_pattern, QueryOptions::default()) do_pattern(triples, graph_pattern, QueryOptions::default())
} }
} }
let query = r#" let query = r#"
@ -92,25 +104,37 @@ fn two_service_test() {
} }
} }
ORDER BY ?name ORDER BY ?name
"#.to_string(); "#
.to_string();
let options = QueryOptions::default().with_service_handler(Box::new(TwoServiceTest)); let options = QueryOptions::default().with_service_handler(Box::new(TwoServiceTest));
let results = do_query(b"".as_ref(), query, options).unwrap(); let results = do_query(b"".as_ref(), query, options).unwrap();
let collected = results.into_values_iter().map(move |b| b.unwrap()).collect::<Vec<_>>(); let collected = results
.into_values_iter()
.map(move |b| b.unwrap())
.collect::<Vec<_>>();
let solution = vec![ let solution = vec![
vec![ Some(literal("Alice".to_string())), Some(mailto("alice@example.com".to_string())) ], vec![
vec![ Some(literal("Bob".to_string())), Some(mailto("bob@example.com".to_string())) ], Some(literal("Alice".to_string())),
Some(mailto("alice@example.com".to_string())),
],
vec![
Some(literal("Bob".to_string())),
Some(mailto("bob@example.com".to_string())),
],
]; ];
assert_eq!(collected, solution); assert_eq!(collected, solution);
} }
#[test] #[test]
fn silent_service_empty_set_test() { fn silent_service_empty_set_test() {
#[derive(Clone, Copy)]
#[derive(Clone,Copy)]
struct ServiceTest; struct ServiceTest;
impl ServiceHandler for ServiceTest { impl ServiceHandler for ServiceTest {
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(ServiceTest::handle_service) Some(ServiceTest::handle_service)
} }
} }
@ -132,23 +156,29 @@ fn silent_service_empty_set_test() {
} }
ORDER BY ?name ORDER BY ?name
"#.to_string(); "#
.to_string();
let triples = b"".as_ref(); let triples = b"".as_ref();
let options = QueryOptions::default().with_service_handler(Box::new(ServiceTest)); let options = QueryOptions::default().with_service_handler(Box::new(ServiceTest));
let results = do_query(triples, query, options).unwrap(); let results = do_query(triples, query, options).unwrap();
let collected = results.into_values_iter().map(move |b| b.unwrap()).collect::<Vec<_>>(); let collected = results
.into_values_iter()
.map(move |b| b.unwrap())
.collect::<Vec<_>>();
println!("Collected: {:?}", collected); println!("Collected: {:?}", collected);
assert_eq!(collected.len(), 0); assert_eq!(collected.len(), 0);
} }
#[test] #[test]
fn non_silent_service_test() { fn non_silent_service_test() {
#[derive(Clone, Copy)]
#[derive(Clone,Copy)]
struct ServiceTest; struct ServiceTest;
impl ServiceHandler for ServiceTest { impl ServiceHandler for ServiceTest {
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(ServiceTest::handle_service) Some(ServiceTest::handle_service)
} }
} }
@ -170,7 +200,8 @@ fn non_silent_service_test() {
} }
ORDER BY ?name ORDER BY ?name
"#.to_string(); "#
.to_string();
let triples = b"".as_ref(); let triples = b"".as_ref();
let options = QueryOptions::default().with_service_handler(Box::new(ServiceTest)); let options = QueryOptions::default().with_service_handler(Box::new(ServiceTest));
@ -178,7 +209,10 @@ fn non_silent_service_test() {
let result = results.into_values_iter().next(); let result = results.into_values_iter().next();
match result { match result {
Some(Err(_)) => assert_eq!(true, true), Some(Err(_)) => assert_eq!(true, true),
_ => assert_eq!(true, false, "This should have been an error since the service fails"), _ => assert_eq!(
true, false,
"This should have been an error since the service fails"
),
} }
} }
@ -197,11 +231,17 @@ fn literal(str: String) -> Term {
fn make_repository(reader: impl BufRead) -> Result<MemoryRepository> { fn make_repository(reader: impl BufRead) -> Result<MemoryRepository> {
let repository = MemoryRepository::default(); let repository = MemoryRepository::default();
let mut connection = repository.connection()?; let mut connection = repository.connection()?;
connection.load_graph(reader, GraphSyntax::NTriples, None, None).unwrap(); connection
.load_graph(reader, GraphSyntax::NTriples, None, None)
.unwrap();
Ok(repository) Ok(repository)
} }
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, None)?; let prepared_query = connection.prepare_query(&query, None)?;
let result = prepared_query.exec(&options)?; let result = prepared_query.exec(&options)?;
@ -209,13 +249,22 @@ fn query_repository<'a>(repository: MemoryRepository, query: String, options: Qu
QueryResult::Bindings(iterator) => { QueryResult::Bindings(iterator) => {
let (varaibles, iter) = iterator.destruct(); let (varaibles, iter) = iterator.destruct();
let collected = iter.collect::<Vec<_>>(); let collected = iter.collect::<Vec<_>>();
Ok(BindingsIterator::new(varaibles, Box::new(collected.into_iter()))) Ok(BindingsIterator::new(
}, varaibles,
_ => Err(format_err!("Excpected bindings but got another QueryResult")) Box::new(collected.into_iter()),
))
}
_ => Err(format_err!(
"Excpected bindings but got another QueryResult"
)),
} }
} }
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, None)?; let prepared_query = connection.prepare_query_from_pattern(&pattern, None)?;
let result = prepared_query.exec(&options)?; let result = prepared_query.exec(&options)?;
@ -223,18 +272,31 @@ fn pattern_repository<'a>(repository: MemoryRepository, pattern: GraphPattern, o
QueryResult::Bindings(iterator) => { QueryResult::Bindings(iterator) => {
let (varaibles, iter) = iterator.destruct(); let (varaibles, iter) = iterator.destruct();
let collected = iter.collect::<Vec<_>>(); let collected = iter.collect::<Vec<_>>();
Ok(BindingsIterator::new(varaibles, Box::new(collected.into_iter()))) Ok(BindingsIterator::new(
varaibles,
Box::new(collected.into_iter()),
))
} }
_ => Err(format_err!("Excpected bindings but got another QueryResult")) _ => Err(format_err!(
"Excpected bindings but got another QueryResult"
)),
} }
} }
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<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)
} }

Loading…
Cancel
Save