From b4065e607ca4b5b8951b726c0eafbd9ebd99e64a Mon Sep 17 00:00:00 2001 From: Tpt Date: Thu, 17 Oct 2019 11:38:35 +0200 Subject: [PATCH] Runs cargo fmt --- lib/src/repository.rs | 6 +- lib/src/sparql/eval.rs | 611 +++++++++++++++++++------------- lib/src/sparql/mod.rs | 30 +- lib/src/sparql/plan.rs | 4 +- lib/src/sparql/plan_builder.rs | 2 +- lib/src/store/mod.rs | 14 +- lib/tests/service_test_cases.rs | 354 ++++++++++-------- 7 files changed, 596 insertions(+), 425 deletions(-) diff --git a/lib/src/repository.rs b/lib/src/repository.rs index 2ee0ad10..097c90cd 100644 --- a/lib/src/repository.rs +++ b/lib/src/repository.rs @@ -83,7 +83,11 @@ pub trait RepositoryConnection: Clone { /// 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; + fn prepare_query<'a>( + &'a self, + query: &str, + base_iri: Option<&'a str>, + ) -> Result; /// 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>( diff --git a/lib/src/sparql/eval.rs b/lib/src/sparql/eval.rs index 989dcb90..1a15002f 100644 --- a/lib/src/sparql/eval.rs +++ b/lib/src/sparql/eval.rs @@ -1,8 +1,8 @@ use crate::model::BlankNode; use crate::model::Triple; use crate::sparql::model::*; -use crate::sparql::QueryOptions; use crate::sparql::plan::*; +use crate::sparql::QueryOptions; use crate::store::numeric_encoder::*; use crate::store::StoreConnection; use crate::Result; @@ -59,7 +59,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { &'b self, plan: &'b PlanNode, variables: &[Variable], - options: &'b QueryOptions<'b> + options: &'b QueryOptions<'b>, ) -> Result> where 'a: 'b, @@ -73,7 +73,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { pub fn evaluate_ask_plan<'b>( &'b self, plan: &'b PlanNode, - options: &'b QueryOptions<'b> + options: &'b QueryOptions<'b>, ) -> Result> where 'a: 'b, @@ -89,7 +89,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { &'b self, plan: &'b PlanNode, construct: &'b [TripleTemplate], - options: &'b QueryOptions<'b> + options: &'b QueryOptions<'b>, ) -> Result> where 'a: 'b, @@ -106,7 +106,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { pub fn evaluate_describe_plan<'b>( &'b self, plan: &'b PlanNode, - options: &'b QueryOptions<'b> + options: &'b QueryOptions<'b>, ) -> Result> where 'a: 'b, @@ -123,7 +123,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { &'b self, node: &'b PlanNode, from: EncodedTuple, - options: &'b QueryOptions<'b> + options: &'b QueryOptions<'b>, ) -> EncodedTuplesIterator<'b> where 'a: 'b, @@ -137,68 +137,70 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { service_name, graph_pattern, .. - } => { - match &options.service_handler { - None => if *silent { + } => match &options.service_handler { + None => { + if *silent { return Box::new(empty()); } else { return Box::new(once(Err(format_err!( "No handler was supplied to resolve the given service" )))) as EncodedTuplesIterator<'_>; - }, - Some(handler) => { - let pattern_option = match get_pattern_value(service_name, &[]) { - None => if *silent { - return Box::new(empty()); - } else { - return Box::new(once(Err(format_err!( - "The handler supplied was unable to evaluate the given service" - )))) as EncodedTuplesIterator<'_>; - }, - Some(term) => { - match self.dataset.decode_named_node(term) { - Err(err) => if *silent { - return Box::new(empty()); - } else { - return Box::new(once(Err(err))) as EncodedTuplesIterator<'_>; - }, - Ok(named_node) => { - println!("named_node: {:?}", named_node); - handler.handle(named_node) - } - + } + } + Some(handler) => { + let pattern_option = match get_pattern_value(service_name, &[]) { + None => { + if *silent { + return Box::new(empty()); + } else { + return Box::new(once(Err(format_err!( + "The handler supplied was unable to evaluate the given service" + )))) + as EncodedTuplesIterator<'_>; + } + } + Some(term) => match self.dataset.decode_named_node(term) { + Err(err) => { + if *silent { + return Box::new(empty()); + } else { + return Box::new(once(Err(err))) as EncodedTuplesIterator<'_>; } - }, - }; - match pattern_option { - None => if *silent { - return Box::new(empty()); - } else { - return Box::new(once(Err(format_err!( + } + Ok(named_node) => { + println!("named_node: {:?}", named_node); + handler.handle(named_node) + } + }, + }; + match pattern_option { + None => { + if *silent { + return Box::new(empty()); + } else { + return Box::new(once(Err(format_err!( "The handler supplied was unable to produce any result set on the given service" )))) as EncodedTuplesIterator<'_>; - }, - Some(pattern_fn) => { - match pattern_fn(graph_pattern.clone()) { - Ok(bindings) => { - let encoded = self.encode_bindings(variables, bindings); - let collected = encoded.collect::>(); - Box::new(JoinIterator { - left: vec![from], - right_iter: Box::new(collected.into_iter()), - buffered_results: vec![], - }) - }, - Err(err) => { - if *silent { - return Box::new(empty()); - } else { - return Box::new(once(Err(err))) as EncodedTuplesIterator<'_> - } - } - } - }, + } } + Some(pattern_fn) => match pattern_fn(graph_pattern.clone()) { + Ok(bindings) => { + let encoded = self.encode_bindings(variables, bindings); + let collected = encoded.collect::>(); + Box::new(JoinIterator { + left: vec![from], + right_iter: Box::new(collected.into_iter()), + buffered_results: vec![], + }) + } + Err(err) => { + if *silent { + return Box::new(empty()); + } else { + return Box::new(once(Err(err))) as EncodedTuplesIterator<'_>; + } + } + }, } } }, @@ -208,127 +210,135 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { predicate, object, graph_name, - } => Box::new(self.eval_plan(&*child, from, options).flat_map_ok(move |tuple| { - let mut iter = self.dataset.quads_for_pattern( - get_pattern_value(&subject, &tuple), - get_pattern_value(&predicate, &tuple), - get_pattern_value(&object, &tuple), - get_pattern_value(&graph_name, &tuple), - options.default_graph_as_union - ); - if subject.is_var() && subject == predicate { - iter = Box::new(iter.filter(|quad| match quad { - Err(_) => true, - Ok(quad) => quad.subject == quad.predicate, - })) - } - if subject.is_var() && subject == object { - iter = Box::new(iter.filter(|quad| match quad { - Err(_) => true, - Ok(quad) => quad.subject == quad.object, - })) - } - if predicate.is_var() && predicate == object { - iter = Box::new(iter.filter(|quad| match quad { - Err(_) => true, - Ok(quad) => quad.predicate == quad.object, - })) - } - if graph_name.is_var() { - iter = Box::new(iter.filter(|quad| match quad { - Err(_) => true, - Ok(quad) => quad.graph_name != ENCODED_DEFAULT_GRAPH, - })); - if graph_name == subject { - iter = Box::new(iter.filter(|quad| match quad { - Err(_) => true, - Ok(quad) => quad.graph_name == quad.subject, - })) - } - if graph_name == predicate { - iter = Box::new(iter.filter(|quad| match quad { - Err(_) => true, - Ok(quad) => quad.graph_name == quad.predicate, - })) - } - if graph_name == object { - iter = Box::new(iter.filter(|quad| match quad { - Err(_) => true, - Ok(quad) => quad.graph_name == quad.object, - })) - } - } - let iter: EncodedTuplesIterator<'_> = Box::new(iter.map(move |quad| { - let quad = quad?; - let mut new_tuple = tuple.clone(); - put_pattern_value(&subject, quad.subject, &mut new_tuple); - put_pattern_value(&predicate, quad.predicate, &mut new_tuple); - put_pattern_value(&object, quad.object, &mut new_tuple); - put_pattern_value(&graph_name, quad.graph_name, &mut new_tuple); - Ok(new_tuple) - })); - iter - })), + } => Box::new( + self.eval_plan(&*child, from, options) + .flat_map_ok(move |tuple| { + let mut iter = self.dataset.quads_for_pattern( + get_pattern_value(&subject, &tuple), + get_pattern_value(&predicate, &tuple), + get_pattern_value(&object, &tuple), + get_pattern_value(&graph_name, &tuple), + options.default_graph_as_union, + ); + if subject.is_var() && subject == predicate { + iter = Box::new(iter.filter(|quad| match quad { + Err(_) => true, + Ok(quad) => quad.subject == quad.predicate, + })) + } + if subject.is_var() && subject == object { + iter = Box::new(iter.filter(|quad| match quad { + Err(_) => true, + Ok(quad) => quad.subject == quad.object, + })) + } + if predicate.is_var() && predicate == object { + iter = Box::new(iter.filter(|quad| match quad { + Err(_) => true, + Ok(quad) => quad.predicate == quad.object, + })) + } + if graph_name.is_var() { + iter = Box::new(iter.filter(|quad| match quad { + Err(_) => true, + Ok(quad) => quad.graph_name != ENCODED_DEFAULT_GRAPH, + })); + if graph_name == subject { + iter = Box::new(iter.filter(|quad| match quad { + Err(_) => true, + Ok(quad) => quad.graph_name == quad.subject, + })) + } + if graph_name == predicate { + iter = Box::new(iter.filter(|quad| match quad { + Err(_) => true, + Ok(quad) => quad.graph_name == quad.predicate, + })) + } + if graph_name == object { + iter = Box::new(iter.filter(|quad| match quad { + Err(_) => true, + Ok(quad) => quad.graph_name == quad.object, + })) + } + } + let iter: EncodedTuplesIterator<'_> = Box::new(iter.map(move |quad| { + let quad = quad?; + let mut new_tuple = tuple.clone(); + put_pattern_value(&subject, quad.subject, &mut new_tuple); + put_pattern_value(&predicate, quad.predicate, &mut new_tuple); + put_pattern_value(&object, quad.object, &mut new_tuple); + put_pattern_value(&graph_name, quad.graph_name, &mut new_tuple); + Ok(new_tuple) + })); + iter + }), + ), PlanNode::PathPatternJoin { child, subject, path, object, graph_name, - } => Box::new(self.eval_plan(&*child, from, options).flat_map_ok(move |tuple| { - let input_subject = get_pattern_value(&subject, &tuple); - let input_object = get_pattern_value(&object, &tuple); - let input_graph_name = - if let Some(graph_name) = get_pattern_value(&graph_name, &tuple) { - graph_name - } else { - return Box::new(once(Err(format_err!( + } => Box::new( + self.eval_plan(&*child, from, options) + .flat_map_ok(move |tuple| { + let input_subject = get_pattern_value(&subject, &tuple); + let input_object = get_pattern_value(&object, &tuple); + let input_graph_name = + if let Some(graph_name) = get_pattern_value(&graph_name, &tuple) { + graph_name + } else { + return Box::new(once(Err(format_err!( "Unknown graph name is not allowed when evaluating property path" )))) as EncodedTuplesIterator<'_>; - }; - match (input_subject, input_object) { - (Some(input_subject), Some(input_object)) => Box::new( - self.eval_path_from(path, input_subject, input_graph_name, options) - .filter_map(move |o| match o { - Ok(o) => { - if o == input_object { - Some(Ok(tuple.clone())) - } else { - None - } - } - Err(error) => Some(Err(error)), - }), - ) - as EncodedTuplesIterator<'_>, - (Some(input_subject), None) => Box::new( - self.eval_path_from(path, input_subject, input_graph_name, options) - .map(move |o| { - let mut new_tuple = tuple.clone(); - put_pattern_value(&object, o?, &mut new_tuple); - Ok(new_tuple) - }), - ), - (None, Some(input_object)) => Box::new( - self.eval_path_to(path, input_object, input_graph_name, options) - .map(move |s| { - let mut new_tuple = tuple.clone(); - put_pattern_value(&subject, s?, &mut new_tuple); - Ok(new_tuple) - }), - ), - (None, None) => { - Box::new(self.eval_open_path(path, input_graph_name, options).map(move |so| { - let mut new_tuple = tuple.clone(); - so.map(move |(s, o)| { - put_pattern_value(&subject, s, &mut new_tuple); - put_pattern_value(&object, o, &mut new_tuple); - new_tuple - }) - })) - } - } - })), + }; + match (input_subject, input_object) { + (Some(input_subject), Some(input_object)) => Box::new( + self.eval_path_from(path, input_subject, input_graph_name, options) + .filter_map(move |o| match o { + Ok(o) => { + if o == input_object { + Some(Ok(tuple.clone())) + } else { + None + } + } + Err(error) => Some(Err(error)), + }), + ) + as EncodedTuplesIterator<'_>, + (Some(input_subject), None) => Box::new( + self.eval_path_from(path, input_subject, input_graph_name, options) + .map(move |o| { + let mut new_tuple = tuple.clone(); + put_pattern_value(&object, o?, &mut new_tuple); + Ok(new_tuple) + }), + ), + (None, Some(input_object)) => Box::new( + self.eval_path_to(path, input_object, input_graph_name, options) + .map(move |s| { + let mut new_tuple = tuple.clone(); + put_pattern_value(&subject, s?, &mut new_tuple); + Ok(new_tuple) + }), + ), + (None, None) => { + Box::new(self.eval_open_path(path, input_graph_name, options).map( + move |so| { + let mut new_tuple = tuple.clone(); + so.map(move |(s, o)| { + put_pattern_value(&subject, s, &mut new_tuple); + put_pattern_value(&object, o, &mut new_tuple); + new_tuple + }) + }, + )) + } + } + }), + ), PlanNode::Join { left, right } => { //TODO: very dumb implementation let mut errors = Vec::default(); @@ -456,7 +466,9 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { PlanNode::HashDeduplicate { child } => { 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 } => { Box::new(self.eval_plan(&*child, from, options).take(*count)) } @@ -513,12 +525,9 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { }); for (i, accumulator) in key_accumulators.iter_mut().enumerate() { let (aggregate, _) = &aggregates[i]; - accumulator.add( - aggregate - .parameter - .as_ref() - .and_then(|parameter| self.eval_expression(¶meter, &tuple, options)), - ); + accumulator.add(aggregate.parameter.as_ref().and_then(|parameter| { + self.eval_expression(¶meter, &tuple, options) + })); } }); if accumulators_for_group.is_empty() { @@ -597,7 +606,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { path: &'b PlanPropertyPath, start: EncodedTerm, graph_name: EncodedTerm, - options: &'b QueryOptions<'b> + options: &'b QueryOptions<'b>, ) -> Box> + 'b> where 'a: 'b, @@ -605,13 +614,21 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { match path { PlanPropertyPath::PredicatePath(p) => Box::new( 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)), ), PlanPropertyPath::InversePath(p) => self.eval_path_to(&p, start, graph_name, options), PlanPropertyPath::SequencePath(a, b) => Box::new( 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( self.eval_path_from(&a, start, graph_name, options) @@ -631,7 +648,13 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { )), PlanPropertyPath::NegatedPropertySet(ps) => Box::new( 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 { Ok(t) => !ps.contains(&t.predicate), Err(_) => true, @@ -646,7 +669,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { path: &'b PlanPropertyPath, end: EncodedTerm, graph_name: EncodedTerm, - options: &'a QueryOptions<'b> + options: &'a QueryOptions<'b>, ) -> Box> + 'b> where 'a: 'b, @@ -654,7 +677,13 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { match path { PlanPropertyPath::PredicatePath(p) => Box::new( 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)), ), PlanPropertyPath::InversePath(p) => self.eval_path_from(&p, end, graph_name, options), @@ -680,7 +709,13 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { )), PlanPropertyPath::NegatedPropertySet(ps) => Box::new( 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 { Ok(t) => !ps.contains(&t.predicate), Err(_) => true, @@ -694,7 +729,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { &'b self, path: &'b PlanPropertyPath, graph_name: EncodedTerm, - options: &'b QueryOptions<'b> + options: &'b QueryOptions<'b>, ) -> Box> + 'b> where 'a: 'b, @@ -702,7 +737,13 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { match path { PlanPropertyPath::PredicatePath(p) => Box::new( 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))), ), PlanPropertyPath::InversePath(p) => Box::new( @@ -740,7 +781,13 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { )), PlanPropertyPath::NegatedPropertySet(ps) => Box::new( 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 { Ok(t) => !ps.contains(&t.predicate), Err(_) => true, @@ -753,10 +800,16 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { fn get_subject_or_object_identity_pairs<'b>( &'b self, graph_name: EncodedTerm, - options: &'b QueryOptions<'b> + options: &'b QueryOptions<'b>, ) -> impl Iterator> + 'b { 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)))) .map(|e| e.map(|e| (e, e))) } @@ -765,21 +818,29 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { &'b self, expression: &PlanExpression, tuple: &[Option], - options: &QueryOptions<'b> + options: &QueryOptions<'b>, ) -> Option { match expression { PlanExpression::Constant(t) => Some(*t), PlanExpression::Variable(v) => get_tuple_value(*v, tuple), - PlanExpression::Exists(node) => { - Some(self.eval_plan(node, tuple.to_vec(), options).next().is_some().into()) - } + PlanExpression::Exists(node) => Some( + self.eval_plan(node, tuple.to_vec(), options) + .next() + .is_some() + .into(), + ), 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(false) => self.eval_expression(b, tuple, options), None => { 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()) } else { @@ -795,7 +856,11 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { Some(true) => self.eval_expression(b, tuple, options), Some(false) => Some(false.into()), 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()) } else { None @@ -864,32 +929,40 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { Some(false.into()) } } - PlanExpression::Add(a, b) => Some(match self.parse_numeric_operands(a, b, tuple, options)? { - NumericBinaryOperands::Float(v1, v2) => (v1 + v2).into(), - NumericBinaryOperands::Double(v1, v2) => (v1 + v2).into(), - NumericBinaryOperands::Integer(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)? { - NumericBinaryOperands::Float(v1, v2) => (v1 - v2).into(), - NumericBinaryOperands::Double(v1, v2) => (v1 - v2).into(), - NumericBinaryOperands::Integer(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)? { - NumericBinaryOperands::Float(v1, v2) => (v1 * v2).into(), - NumericBinaryOperands::Double(v1, v2) => (v1 * v2).into(), - NumericBinaryOperands::Integer(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)? { - NumericBinaryOperands::Float(v1, v2) => (v1 / v2).into(), - NumericBinaryOperands::Double(v1, v2) => (v1 / v2).into(), - NumericBinaryOperands::Integer(v1, v2) => Decimal::from_i128(v1)? - .checked_div(Decimal::from_i128(v2)?)? - .into(), - NumericBinaryOperands::Decimal(v1, v2) => v1.checked_div(v2)?.into(), - }), + PlanExpression::Add(a, b) => { + Some(match self.parse_numeric_operands(a, b, tuple, options)? { + NumericBinaryOperands::Float(v1, v2) => (v1 + v2).into(), + NumericBinaryOperands::Double(v1, v2) => (v1 + v2).into(), + NumericBinaryOperands::Integer(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)? { + NumericBinaryOperands::Float(v1, v2) => (v1 - v2).into(), + NumericBinaryOperands::Double(v1, v2) => (v1 - v2).into(), + NumericBinaryOperands::Integer(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)? { + NumericBinaryOperands::Float(v1, v2) => (v1 * v2).into(), + NumericBinaryOperands::Double(v1, v2) => (v1 * v2).into(), + NumericBinaryOperands::Integer(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)? { + NumericBinaryOperands::Float(v1, v2) => (v1 / v2).into(), + NumericBinaryOperands::Double(v1, v2) => (v1 / v2).into(), + NumericBinaryOperands::Integer(v1, v2) => Decimal::from_i128(v1)? + .checked_div(Decimal::from_i128(v2)?)? + .into(), + NumericBinaryOperands::Decimal(v1, v2) => v1.checked_div(v2)?.into(), + }) + } PlanExpression::UnaryPlus(e) => match self.eval_expression(e, tuple, options)? { EncodedTerm::FloatLiteral(value) => Some((*value).into()), EncodedTerm::DoubleLiteral(value) => Some((*value).into()), @@ -950,9 +1023,10 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { _ => None, }?; let iri = self.dataset.get_str(iri_id).ok()??; - let base_iri = options.base_iri - .map(|base_iri| Iri::parse(base_iri.to_string())) - .or(self.base_iri.as_ref().map(|iri| Ok(iri.clone()))); + let base_iri = options + .base_iri + .map(|base_iri| Iri::parse(base_iri.to_string())) + .or(self.base_iri.as_ref().map(|iri| Ok(iri.clone()))); if let Some(Ok(base_iri)) = base_iri { self.build_named_node(&base_iri.resolve(&iri).ok()?.into_inner()) } else { @@ -1043,7 +1117,9 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { return None; }; let length: Option = 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()?) } else { return None; @@ -1313,14 +1389,18 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { } PlanExpression::StrLang(lexical_form, lang_tag) => { Some(EncodedTerm::LangStringLiteral { - value_id: self - .to_simple_string_id(self.eval_expression(lexical_form, tuple, options)?)?, + value_id: self.to_simple_string_id(self.eval_expression( + lexical_form, + tuple, + options, + )?)?, language_id: self .to_simple_string_id(self.eval_expression(lang_tag, tuple, options)?)?, }) } 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 } = self.eval_expression(datatype, tuple, options)? { @@ -1336,15 +1416,21 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { }) .ok() } - PlanExpression::SameTerm(a, b) => { - Some((self.eval_expression(a, tuple, options)? == self.eval_expression(b, tuple, options)?).into()) - } - PlanExpression::IsIRI(e) => { - Some(self.eval_expression(e, tuple, options)?.is_named_node().into()) - } - PlanExpression::IsBlank(e) => { - Some(self.eval_expression(e, tuple, options)?.is_blank_node().into()) - } + PlanExpression::SameTerm(a, b) => Some( + (self.eval_expression(a, tuple, options)? + == self.eval_expression(b, tuple, options)?) + .into(), + ), + PlanExpression::IsIRI(e) => Some( + self.eval_expression(e, tuple, options)? + .is_named_node() + .into(), + ), + PlanExpression::IsBlank(e) => Some( + self.eval_expression(e, tuple, options)? + .is_blank_node() + .into(), + ), PlanExpression::IsLiteral(e) => { Some(self.eval_expression(e, tuple, options)?.is_literal().into()) } @@ -1630,7 +1716,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { e1: &PlanExpression, e2: &PlanExpression, tuple: &[Option], - options: &QueryOptions<'b> + options: &QueryOptions<'b>, ) -> Option { NumericBinaryOperands::new( self.eval_expression(&e1, tuple, options)?, @@ -1687,7 +1773,12 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { Some(term) => { if let Ok(encoded) = encoder.encode_term(&term) { 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 { })) } - #[allow(clippy::float_cmp)] fn equals(&self, a: EncodedTerm, b: EncodedTerm) -> Option { match a { @@ -1814,7 +1904,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { tuple_a: &[Option], tuple_b: &[Option], expression: &PlanExpression, - options: &QueryOptions<'b> + options: &QueryOptions<'b>, ) -> Ordering { self.cmp_terms( self.eval_expression(expression, tuple_a, options), @@ -1933,7 +2023,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { &'b self, arg: &PlanExpression, tuple: &[Option], - options: &QueryOptions<'b> + options: &QueryOptions<'b>, ) -> Option { let input = self.to_simple_string(self.eval_expression(arg, tuple, options)?)?; 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() { if selector == v { 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) { if position < tuple.len() { tuple[position] = Some(value) @@ -2226,7 +2320,9 @@ impl<'a, S: StoreConnection> Iterator for LeftJoinIterator<'a, S> { } match self.left_iter.next()? { 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() { Some(right_tuple) } else { @@ -2294,9 +2390,11 @@ impl<'a, S: StoreConnection> Iterator for UnionIterator<'a, S> { if self.current_plan >= self.plans.len() { return None; } - self.current_iterator = self - .eval - .eval_plan(&self.plans[self.current_plan], self.input.clone(), self.options); + self.current_iterator = self.eval.eval_plan( + &self.plans[self.current_plan], + self.input.clone(), + self.options, + ); self.current_plan += 1; } } @@ -2401,10 +2499,13 @@ impl<'a, S: StoreConnection + 'a> Iterator for DescribeIterator<'a, S> { }; for subject in tuple { if let Some(subject) = subject { - self.quads = - self.eval - .dataset - .quads_for_pattern(Some(subject), None, None, None, self.options.default_graph_as_union); + self.quads = self.eval.dataset.quads_for_pattern( + Some(subject), + None, + None, + None, + self.options.default_graph_as_union, + ); } } } diff --git a/lib/src/sparql/mod.rs b/lib/src/sparql/mod.rs index 5593b3b7..6b93c208 100644 --- a/lib/src/sparql/mod.rs +++ b/lib/src/sparql/mod.rs @@ -121,27 +121,24 @@ impl<'a, S: StoreConnection + 'a> SimplePreparedQuery { pub(crate) fn new_from_pattern( connection: S, pattern: &GraphPattern, - base_iri: Option<&'a str> + base_iri: Option<&'a str>, ) -> Result { let dataset = DatasetView::new(connection); let (plan, variables) = PlanBuilder::build(dataset.encoder(), pattern)?; let base_iri = base_iri.map(|str_iri| Iri::parse(str_iri.to_string())); match base_iri { Some(Err(_)) => Err(format_err!("Failed to parse base_iri")), - Some(Ok(base_iri)) => - Ok(Self(SimplePreparedQueryAction::Select { - plan, - variables, - evaluator: SimpleEvaluator::new(dataset, Some(base_iri)), - })), - None => - Ok(Self(SimplePreparedQueryAction::Select { - plan, - variables, - evaluator: SimpleEvaluator::new(dataset, None), - })) + Some(Ok(base_iri)) => Ok(Self(SimplePreparedQueryAction::Select { + plan, + variables, + evaluator: SimpleEvaluator::new(dataset, Some(base_iri)), + })), + None => Ok(Self(SimplePreparedQueryAction::Select { + plan, + variables, + evaluator: SimpleEvaluator::new(dataset, None), + })), } - } } @@ -169,7 +166,10 @@ impl PreparedQuery for SimplePreparedQuery { } pub trait ServiceHandler { - fn handle<'a>(&'a self, node: NamedNode) -> Option<(fn(GraphPattern) -> Result>)>; + fn handle<'a>( + &'a self, + node: NamedNode, + ) -> Option<(fn(GraphPattern) -> Result>)>; } /// Options for SPARQL query parsing and evaluation like the query base IRI diff --git a/lib/src/sparql/plan.rs b/lib/src/sparql/plan.rs index 9b84a8aa..970f4b58 100644 --- a/lib/src/sparql/plan.rs +++ b/lib/src/sparql/plan.rs @@ -1,6 +1,6 @@ -use crate::sparql::GraphPattern; -use crate::sparql::model::Variable; use crate::sparql::eval::StringOrStoreString; +use crate::sparql::model::Variable; +use crate::sparql::GraphPattern; use crate::store::numeric_encoder::{ EncodedQuad, EncodedTerm, Encoder, MemoryStrStore, StrContainer, StrLookup, ENCODED_DEFAULT_GRAPH, diff --git a/lib/src/sparql/plan_builder.rs b/lib/src/sparql/plan_builder.rs index e75051e4..a32da1a0 100644 --- a/lib/src/sparql/plan_builder.rs +++ b/lib/src/sparql/plan_builder.rs @@ -113,7 +113,7 @@ impl PlanBuilder { graph_pattern, silent: *s, } - }, + } GraphPattern::AggregateJoin(GroupPattern(key, p), aggregates) => { let mut inner_variables = key.clone(); let inner_graph_name = diff --git a/lib/src/store/mod.rs b/lib/src/store/mod.rs index bcc6cdf3..fd421570 100644 --- a/lib/src/store/mod.rs +++ b/lib/src/store/mod.rs @@ -11,7 +11,7 @@ pub use crate::store::memory::MemoryRepository; pub use crate::store::rocksdb::RocksDbRepository; use crate::model::*; -use crate::sparql::{SimplePreparedQuery}; +use crate::sparql::SimplePreparedQuery; use crate::store::numeric_encoder::*; use crate::{DatasetSyntax, GraphSyntax, RepositoryConnection, Result}; use rio_api::parser::{QuadsParser, TriplesParser}; @@ -72,7 +72,11 @@ impl From for StoreRepositoryConnection { impl RepositoryConnection for StoreRepositoryConnection { type PreparedQuery = SimplePreparedQuery; - fn prepare_query<'a>(&self, query: &str, base_iri: Option<&'a str>) -> Result> { + fn prepare_query<'a>( + &self, + query: &str, + base_iri: Option<&'a str>, + ) -> Result> { SimplePreparedQuery::new(self.inner.clone(), query, base_iri) //TODO: avoid clone } @@ -97,13 +101,13 @@ impl RepositoryConnection for StoreRepositoryConnection { ) } - fn prepare_query_from_pattern<'a>( &'a self, pattern: &GraphPattern, - base_iri: Option<&'a str> + base_iri: Option<&'a str>, ) -> Result { - 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( diff --git a/lib/tests/service_test_cases.rs b/lib/tests/service_test_cases.rs index e6971a78..d1a173db 100644 --- a/lib/tests/service_test_cases.rs +++ b/lib/tests/service_test_cases.rs @@ -1,26 +1,30 @@ -use rudf::model::*; -use rudf::{GraphSyntax, Repository, RepositoryConnection, MemoryRepository, Result}; -use rudf::sparql::{BindingsIterator, GraphPattern, PreparedQuery, QueryOptions, QueryResult, ServiceHandler}; 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; - - #[test] fn simple_service_test() { - - struct TestServiceHandler; - impl ServiceHandler for TestServiceHandler { - fn handle<'a>(&'a self, _named_node: NamedNode) -> Option<(fn(GraphPattern) -> Result>)> { - fn pattern_handler<'a>(graph_pattern: GraphPattern) -> Result> { - let triples = b" .".as_ref(); - do_pattern(triples, graph_pattern, QueryOptions::default()) - }; - Some(pattern_handler) + struct TestServiceHandler; + impl ServiceHandler for TestServiceHandler { + fn handle<'a>( + &'a self, + _named_node: NamedNode, + ) -> Option<(fn(GraphPattern) -> Result>)> { + fn pattern_handler<'a>(graph_pattern: GraphPattern) -> Result> { + let triples = + b" ." + .as_ref(); + do_pattern(triples, graph_pattern, QueryOptions::default()) + }; + Some(pattern_handler) + } } - } - let query = r#" + let query = r#" SELECT ?s ?p ?o WHERE { @@ -28,57 +32,65 @@ fn simple_service_test() { { ?s ?p ?o } } - "#.to_string(); - - - let options = QueryOptions::default().with_service_handler(Box::new(TestServiceHandler)); - let results = do_query(b"".as_ref(), query, options).unwrap(); - let collected = results.into_values_iter().map(move |b| b.unwrap()).collect::>(); - let solution = vec![ - vec![ Some(ex(String::from("s"))), Some(ex(String::from("p"))), Some(ex(String::from("o"))) ], - ]; - assert_eq!(collected, solution); - + "# + .to_string(); + + let options = QueryOptions::default().with_service_handler(Box::new(TestServiceHandler)); + let results = do_query(b"".as_ref(), query, options).unwrap(); + let collected = results + .into_values_iter() + .map(move |b| b.unwrap()) + .collect::>(); + let solution = vec![vec![ + Some(ex(String::from("s"))), + Some(ex(String::from("p"))), + Some(ex(String::from("o"))), + ]]; + assert_eq!(collected, solution); } - #[test] fn two_service_test() { + #[derive(Clone, Copy)] + struct TwoServiceTest; + impl ServiceHandler for TwoServiceTest { + fn handle<'a>( + &'a self, + named_node: NamedNode, + ) -> Option<(fn(GraphPattern) -> Result>)> { + let service1 = NamedNode::parse("http://service1.org").unwrap(); + let service2 = NamedNode::parse("http://service2.org").unwrap(); + if named_node == service1 { + Some(TwoServiceTest::handle_service1) + } else if named_node == service2 { + Some(TwoServiceTest::handle_service2) + } else { + None + } + } + } - #[derive(Clone,Copy)] - struct TwoServiceTest; - impl ServiceHandler for TwoServiceTest { - fn handle<'a>(&'a self, named_node: NamedNode) -> Option<(fn(GraphPattern) -> Result>)> { - let service1 = NamedNode::parse("http://service1.org").unwrap(); - let service2 = NamedNode::parse("http://service2.org").unwrap(); - if named_node == service1 { Some(TwoServiceTest::handle_service1) } - else if named_node == service2 { Some(TwoServiceTest::handle_service2) } - else { None } - } - } - - - impl TwoServiceTest { - - fn handle_service1<'a>(graph_pattern: GraphPattern) -> Result> { - let triples = br#" + impl TwoServiceTest { + fn handle_service1<'a>(graph_pattern: GraphPattern) -> Result> { + let triples = br#" "Bob" . "Alice" . - "#.as_ref(); - do_pattern(triples, graph_pattern, QueryOptions::default()) - } + "# + .as_ref(); + do_pattern(triples, graph_pattern, QueryOptions::default()) + } - fn handle_service2<'a>(graph_pattern: GraphPattern) -> Result> { - let triples = br#" + fn handle_service2<'a>(graph_pattern: GraphPattern) -> Result> { + let triples = br#" . . - "#.as_ref(); - do_pattern(triples, graph_pattern, QueryOptions::default()) + "# + .as_ref(); + do_pattern(triples, graph_pattern, QueryOptions::default()) + } } - } - - let query = r#" + let query = r#" PREFIX foaf: SELECT ?name ?mbox WHERE @@ -92,36 +104,48 @@ fn two_service_test() { } } ORDER BY ?name - "#.to_string(); - - let options = QueryOptions::default().with_service_handler(Box::new(TwoServiceTest)); - let results = do_query(b"".as_ref(), query, options).unwrap(); - let collected = results.into_values_iter().map(move |b| b.unwrap()).collect::>(); - let solution = vec![ - vec![ 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())) ], + "# + .to_string(); + + let options = QueryOptions::default().with_service_handler(Box::new(TwoServiceTest)); + let results = do_query(b"".as_ref(), query, options).unwrap(); + let collected = results + .into_values_iter() + .map(move |b| b.unwrap()) + .collect::>(); + let solution = vec![ + vec![ + 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] fn silent_service_empty_set_test() { + #[derive(Clone, Copy)] + struct ServiceTest; + impl ServiceHandler for ServiceTest { + fn handle<'a>( + &'a self, + _named_node: NamedNode, + ) -> Option<(fn(GraphPattern) -> Result>)> { + Some(ServiceTest::handle_service) + } + } - #[derive(Clone,Copy)] - struct ServiceTest; - impl ServiceHandler for ServiceTest { - fn handle<'a>(&'a self, _named_node: NamedNode) -> Option<(fn(GraphPattern) -> Result>)> { - Some(ServiceTest::handle_service) - } - } - - impl ServiceTest { - fn handle_service<'a>(_graph_pattern: GraphPattern) -> Result> { - Err(format_err!("This is supposed to fail")) + impl ServiceTest { + fn handle_service<'a>(_graph_pattern: GraphPattern) -> Result> { + Err(format_err!("This is supposed to fail")) + } } - } - let query = r#" + let query = r#" PREFIX foaf: SELECT ?name ?mbox WHERE @@ -132,34 +156,40 @@ fn silent_service_empty_set_test() { } ORDER BY ?name - "#.to_string(); - - let triples = b"".as_ref(); - let options = QueryOptions::default().with_service_handler(Box::new(ServiceTest)); - let results = do_query(triples, query, options).unwrap(); - let collected = results.into_values_iter().map(move |b| b.unwrap()).collect::>(); - println!("Collected: {:?}", collected); - assert_eq!(collected.len(), 0); + "# + .to_string(); + + let triples = b"".as_ref(); + let options = QueryOptions::default().with_service_handler(Box::new(ServiceTest)); + let results = do_query(triples, query, options).unwrap(); + let collected = results + .into_values_iter() + .map(move |b| b.unwrap()) + .collect::>(); + println!("Collected: {:?}", collected); + assert_eq!(collected.len(), 0); } #[test] fn non_silent_service_test() { + #[derive(Clone, Copy)] + struct ServiceTest; + impl ServiceHandler for ServiceTest { + fn handle<'a>( + &'a self, + _named_node: NamedNode, + ) -> Option<(fn(GraphPattern) -> Result>)> { + Some(ServiceTest::handle_service) + } + } - #[derive(Clone,Copy)] - struct ServiceTest; - impl ServiceHandler for ServiceTest { - fn handle<'a>(&'a self, _named_node: NamedNode) -> Option<(fn(GraphPattern) -> Result>)> { - Some(ServiceTest::handle_service) - } - } - - impl ServiceTest { - fn handle_service<'a>(_graph_pattern: GraphPattern) -> Result> { - Err(format_err!("This is supposed to fail")) + impl ServiceTest { + fn handle_service<'a>(_graph_pattern: GraphPattern) -> Result> { + Err(format_err!("This is supposed to fail")) + } } - } - let query = r#" + let query = r#" PREFIX foaf: SELECT ?name WHERE @@ -170,71 +200,103 @@ fn non_silent_service_test() { } ORDER BY ?name - "#.to_string(); - - let triples = b"".as_ref(); - let options = QueryOptions::default().with_service_handler(Box::new(ServiceTest)); - let results = do_query(triples, query, options).unwrap(); - let result = results.into_values_iter().next(); - match result { - Some(Err(_)) => assert_eq!(true, true), - _ => assert_eq!(true, false, "This should have been an error since the service fails"), - } + "# + .to_string(); + + let triples = b"".as_ref(); + let options = QueryOptions::default().with_service_handler(Box::new(ServiceTest)); + let results = do_query(triples, query, options).unwrap(); + let result = results.into_values_iter().next(); + match result { + Some(Err(_)) => assert_eq!(true, true), + _ => assert_eq!( + true, false, + "This should have been an error since the service fails" + ), + } } fn ex(id: String) -> Term { - Term::NamedNode(NamedNode::parse(format!("http://example.com/{}", &id)).unwrap()) + Term::NamedNode(NamedNode::parse(format!("http://example.com/{}", &id)).unwrap()) } fn mailto(id: String) -> Term { - Term::NamedNode(NamedNode::parse(format!("mailto:{}", &id)).unwrap()) + Term::NamedNode(NamedNode::parse(format!("mailto:{}", &id)).unwrap()) } fn literal(str: String) -> Term { - Term::Literal(Literal::new_simple_literal(str)) + Term::Literal(Literal::new_simple_literal(str)) } fn make_repository(reader: impl BufRead) -> Result { - let repository = MemoryRepository::default(); - let mut connection = repository.connection()?; - connection.load_graph(reader, GraphSyntax::NTriples, None, None).unwrap(); - Ok(repository) + let repository = MemoryRepository::default(); + let mut connection = repository.connection()?; + connection + .load_graph(reader, GraphSyntax::NTriples, None, None) + .unwrap(); + Ok(repository) +} + +fn query_repository<'a>( + repository: MemoryRepository, + query: String, + options: QueryOptions<'a>, +) -> Result> { + let connection = repository.connection()?; + let prepared_query = connection.prepare_query(&query, None)?; + let result = prepared_query.exec(&options)?; + match result { + QueryResult::Bindings(iterator) => { + let (varaibles, iter) = iterator.destruct(); + let collected = iter.collect::>(); + Ok(BindingsIterator::new( + varaibles, + Box::new(collected.into_iter()), + )) + } + _ => Err(format_err!( + "Excpected bindings but got another QueryResult" + )), + } } -fn query_repository<'a>(repository: MemoryRepository, query: String, options: QueryOptions<'a>) -> Result> { - let connection = repository.connection()?; - let prepared_query = connection.prepare_query(&query, None)?; - let result = prepared_query.exec(&options)?; - match result { - QueryResult::Bindings(iterator) => { - let (varaibles, iter) = iterator.destruct(); - let collected = iter.collect::>(); - Ok(BindingsIterator::new(varaibles, 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> { - let connection = repository.connection()?; - let prepared_query = connection.prepare_query_from_pattern(&pattern, None)?; - let result = prepared_query.exec(&options)?; - match result { - QueryResult::Bindings(iterator) => { - let (varaibles, iter) = iterator.destruct(); - let collected = iter.collect::>(); - Ok(BindingsIterator::new(varaibles, Box::new(collected.into_iter()))) +fn pattern_repository<'a>( + repository: MemoryRepository, + pattern: GraphPattern, + options: QueryOptions<'a>, +) -> Result> { + let connection = repository.connection()?; + let prepared_query = connection.prepare_query_from_pattern(&pattern, None)?; + let result = prepared_query.exec(&options)?; + match result { + QueryResult::Bindings(iterator) => { + let (varaibles, iter) = iterator.destruct(); + let collected = iter.collect::>(); + 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> { - let repository = make_repository(reader)?; - query_repository(repository, query, options) +fn do_query<'a>( + reader: impl BufRead, + query: String, + options: QueryOptions<'a>, +) -> Result> { + let repository = make_repository(reader)?; + query_repository(repository, query, options) } -fn do_pattern<'a>(reader: impl BufRead, pattern: GraphPattern, options: QueryOptions<'a>) -> Result> { - let repository = make_repository(reader)?; - pattern_repository(repository, pattern, options) +fn do_pattern<'a>( + reader: impl BufRead, + pattern: GraphPattern, + options: QueryOptions<'a>, +) -> Result> { + let repository = make_repository(reader)?; + pattern_repository(repository, pattern, options) }