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. 158
      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()));
/// }
/// ```
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.
fn prepare_query_from_pattern<'a>(

@ -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<S> {
&'b self,
plan: &'b PlanNode,
variables: &[Variable],
options: &'b QueryOptions<'b>
options: &'b QueryOptions<'b>,
) -> Result<QueryResult<'b>>
where
'a: 'b,
@ -73,7 +73,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
pub fn evaluate_ask_plan<'b>(
&'b self,
plan: &'b PlanNode,
options: &'b QueryOptions<'b>
options: &'b QueryOptions<'b>,
) -> Result<QueryResult<'b>>
where
'a: 'b,
@ -89,7 +89,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
&'b self,
plan: &'b PlanNode,
construct: &'b [TripleTemplate],
options: &'b QueryOptions<'b>
options: &'b QueryOptions<'b>,
) -> Result<QueryResult<'b>>
where
'a: 'b,
@ -106,7 +106,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
pub fn evaluate_describe_plan<'b>(
&'b self,
plan: &'b PlanNode,
options: &'b QueryOptions<'b>
options: &'b QueryOptions<'b>,
) -> Result<QueryResult<'b>>
where
'a: 'b,
@ -123,7 +123,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
&'b self,
node: &'b PlanNode,
from: EncodedTuple,
options: &'b QueryOptions<'b>
options: &'b QueryOptions<'b>,
) -> EncodedTuplesIterator<'b>
where
'a: 'b,
@ -137,49 +137,53 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
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 {
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 {
))))
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)
}
}
},
};
match pattern_option {
None => if *silent {
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()) {
}
}
Some(pattern_fn) => match pattern_fn(graph_pattern.clone()) {
Ok(bindings) => {
let encoded = self.encode_bindings(variables, bindings);
let collected = encoded.collect::<Vec<_>>();
@ -188,19 +192,17 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
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<'_>
}
return Box::new(once(Err(err))) as EncodedTuplesIterator<'_>;
}
}
},
}
}
}
},
PlanNode::QuadPatternJoin {
child,
@ -208,13 +210,15 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
predicate,
object,
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(
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
options.default_graph_as_union,
);
if subject.is_var() && subject == predicate {
iter = Box::new(iter.filter(|quad| match quad {
@ -268,14 +272,17 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
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| {
} => 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 =
@ -318,17 +325,20 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
}),
),
(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();
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<S> {
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<S> {
});
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(&parameter, &tuple, options)),
);
accumulator.add(aggregate.parameter.as_ref().and_then(|parameter| {
self.eval_expression(&parameter, &tuple, options)
}));
}
});
if accumulators_for_group.is_empty() {
@ -597,7 +606,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
path: &'b PlanPropertyPath,
start: EncodedTerm,
graph_name: EncodedTerm,
options: &'b QueryOptions<'b>
options: &'b QueryOptions<'b>,
) -> Box<dyn Iterator<Item = Result<EncodedTerm>> + 'b>
where
'a: 'b,
@ -605,13 +614,21 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
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<S> {
)),
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<S> {
path: &'b PlanPropertyPath,
end: EncodedTerm,
graph_name: EncodedTerm,
options: &'a QueryOptions<'b>
options: &'a QueryOptions<'b>,
) -> Box<dyn Iterator<Item = Result<EncodedTerm>> + 'b>
where
'a: 'b,
@ -654,7 +677,13 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
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<S> {
)),
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<S> {
&'b self,
path: &'b PlanPropertyPath,
graph_name: EncodedTerm,
options: &'b QueryOptions<'b>
options: &'b QueryOptions<'b>,
) -> Box<dyn Iterator<Item = Result<(EncodedTerm, EncodedTerm)>> + 'b>
where
'a: 'b,
@ -702,7 +737,13 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
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<S> {
)),
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<S> {
fn get_subject_or_object_identity_pairs<'b>(
&'b self,
graph_name: EncodedTerm,
options: &'b QueryOptions<'b>
options: &'b QueryOptions<'b>,
) -> impl Iterator<Item = Result<(EncodedTerm, EncodedTerm)>> + '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<S> {
&'b self,
expression: &PlanExpression,
tuple: &[Option<EncodedTerm>],
options: &QueryOptions<'b>
options: &QueryOptions<'b>,
) -> Option<EncodedTerm> {
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<S> {
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<S> {
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::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)? {
})
}
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)? {
})
}
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)? {
})
}
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,7 +1023,8 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
_ => None,
}?;
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()))
.or(self.base_iri.as_ref().map(|iri| Ok(iri.clone())));
if let Some(Ok(base_iri)) = base_iri {
@ -1043,7 +1117,9 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
return None;
};
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()?)
} else {
return None;
@ -1313,14 +1389,18 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
}
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<S> {
})
.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<S> {
e1: &PlanExpression,
e2: &PlanExpression,
tuple: &[Option<EncodedTerm>],
options: &QueryOptions<'b>
options: &QueryOptions<'b>,
) -> Option<NumericBinaryOperands> {
NumericBinaryOperands::new(
self.eval_expression(&e1, tuple, options)?,
@ -1687,7 +1773,12 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
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<S> {
}))
}
#[allow(clippy::float_cmp)]
fn equals(&self, a: EncodedTerm, b: EncodedTerm) -> Option<bool> {
match a {
@ -1814,7 +1904,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
tuple_a: &[Option<EncodedTerm>],
tuple_b: &[Option<EncodedTerm>],
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<S> {
&'b self,
arg: &PlanExpression,
tuple: &[Option<EncodedTerm>],
options: &QueryOptions<'b>
options: &QueryOptions<'b>,
) -> Option<EncodedTerm> {
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,
);
}
}
}

@ -121,27 +121,24 @@ impl<'a, S: StoreConnection + 'a> SimplePreparedQuery<S> {
pub(crate) fn new_from_pattern(
connection: S,
pattern: &GraphPattern,
base_iri: Option<&'a str>
base_iri: Option<&'a str>,
) -> Result<Self> {
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 {
Some(Ok(base_iri)) => Ok(Self(SimplePreparedQueryAction::Select {
plan,
variables,
evaluator: SimpleEvaluator::new(dataset, Some(base_iri)),
})),
None =>
Ok(Self(SimplePreparedQueryAction::Select {
None => Ok(Self(SimplePreparedQueryAction::Select {
plan,
variables,
evaluator: SimpleEvaluator::new(dataset, None),
}))
})),
}
}
}
@ -169,7 +166,10 @@ impl<S: StoreConnection> PreparedQuery for SimplePreparedQuery<S> {
}
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

@ -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,

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

@ -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<S: StoreConnection> From<S> for StoreRepositoryConnection<S> {
impl<S: StoreConnection> RepositoryConnection for StoreRepositoryConnection<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
}
@ -97,13 +101,13 @@ impl<S: StoreConnection> RepositoryConnection for StoreRepositoryConnection<S> {
)
}
fn prepare_query_from_pattern<'a>(
&'a self,
pattern: &GraphPattern,
base_iri: Option<&'a str>
base_iri: Option<&'a str>,
) -> 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(

@ -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 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<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>> {
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())
};
Some(pattern_handler)
@ -28,43 +32,51 @@ fn simple_service_test() {
{ ?s ?p ?o
}
}
"#.to_string();
"#
.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::<Vec<_>>();
let solution = vec![
vec![ Some(ex(String::from("s"))), Some(ex(String::from("p"))), Some(ex(String::from("o"))) ],
];
let collected = results
.into_values_iter()
.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);
}
#[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<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 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 }
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<BindingsIterator<'a>> {
let triples = br#"
<http://example.com/bob> <http://xmlns.com/foaf/0.1/name> "Bob" .
<http://example.com/alice> <http://xmlns.com/foaf/0.1/name> "Alice" .
"#.as_ref();
"#
.as_ref();
do_pattern(triples, graph_pattern, QueryOptions::default())
}
@ -72,10 +84,10 @@ fn two_service_test() {
let triples = br#"
<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> .
"#.as_ref();
"#
.as_ref();
do_pattern(triples, graph_pattern, QueryOptions::default())
}
}
let query = r#"
@ -92,25 +104,37 @@ fn two_service_test() {
}
}
ORDER BY ?name
"#.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::<Vec<_>>();
let collected = results
.into_values_iter()
.map(move |b| b.unwrap())
.collect::<Vec<_>>();
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())) ],
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);
}
#[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<BindingsIterator<'a>>)> {
fn handle<'a>(
&'a self,
_named_node: NamedNode,
) -> Option<(fn(GraphPattern) -> Result<BindingsIterator<'a>>)> {
Some(ServiceTest::handle_service)
}
}
@ -132,23 +156,29 @@ fn silent_service_empty_set_test() {
}
ORDER BY ?name
"#.to_string();
"#
.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::<Vec<_>>();
let collected = results
.into_values_iter()
.map(move |b| b.unwrap())
.collect::<Vec<_>>();
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<BindingsIterator<'a>>)> {
fn handle<'a>(
&'a self,
_named_node: NamedNode,
) -> Option<(fn(GraphPattern) -> Result<BindingsIterator<'a>>)> {
Some(ServiceTest::handle_service)
}
}
@ -170,7 +200,8 @@ fn non_silent_service_test() {
}
ORDER BY ?name
"#.to_string();
"#
.to_string();
let triples = b"".as_ref();
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();
match result {
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> {
let repository = MemoryRepository::default();
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)
}
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 prepared_query = connection.prepare_query(&query, None)?;
let result = prepared_query.exec(&options)?;
@ -209,13 +249,22 @@ fn query_repository<'a>(repository: MemoryRepository, query: String, options: Qu
QueryResult::Bindings(iterator) => {
let (varaibles, iter) = iterator.destruct();
let collected = iter.collect::<Vec<_>>();
Ok(BindingsIterator::new(varaibles, Box::new(collected.into_iter())))
},
_ => Err(format_err!("Excpected bindings but got another QueryResult"))
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<BindingsIterator<'a>> {
fn pattern_repository<'a>(
repository: MemoryRepository,
pattern: GraphPattern,
options: QueryOptions<'a>,
) -> Result<BindingsIterator<'a>> {
let connection = repository.connection()?;
let prepared_query = connection.prepare_query_from_pattern(&pattern, None)?;
let result = prepared_query.exec(&options)?;
@ -223,18 +272,31 @@ fn pattern_repository<'a>(repository: MemoryRepository, pattern: GraphPattern, o
QueryResult::Bindings(iterator) => {
let (varaibles, iter) = iterator.destruct();
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)?;
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)?;
pattern_repository(repository, pattern, options)
}

Loading…
Cancel
Save