Implements SPARQL-star nested triple patterns evaluation

pull/171/head
Tpt 4 years ago
parent ae0422d21c
commit 7e9e3a0743
  1. 189
      lib/src/sparql/eval.rs
  2. 14
      lib/src/sparql/plan.rs
  3. 59
      lib/src/sparql/plan_builder.rs

@ -141,63 +141,27 @@ impl SimpleEvaluator {
let object = object.clone(); let object = object.clone();
let graph_name = graph_name.clone(); let graph_name = graph_name.clone();
Box::new(self.eval_plan(child, from).flat_map_ok(move |tuple| { Box::new(self.eval_plan(child, from).flat_map_ok(move |tuple| {
let mut iter: Box<dyn Iterator<Item = _>> = let iter = eval.dataset.encoded_quads_for_pattern(
Box::new(eval.dataset.encoded_quads_for_pattern( get_pattern_value(&subject, &tuple).as_ref(),
get_pattern_value(&subject, &tuple), get_pattern_value(&predicate, &tuple).as_ref(),
get_pattern_value(&predicate, &tuple), get_pattern_value(&object, &tuple).as_ref(),
get_pattern_value(&object, &tuple), get_pattern_value(&graph_name, &tuple).as_ref(),
get_pattern_value(&graph_name, &tuple), );
));
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() {
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 subject = subject.clone(); let subject = subject.clone();
let predicate = predicate.clone(); let predicate = predicate.clone();
let object = object.clone(); let object = object.clone();
let graph_name = graph_name.clone(); let graph_name = graph_name.clone();
let iter: EncodedTuplesIterator = Box::new(iter.map(move |quad| { let iter: EncodedTuplesIterator =
let quad = quad?; Box::new(iter.filter_map(move |quad| match quad {
Ok(quad) => {
let mut new_tuple = tuple.clone(); let mut new_tuple = tuple.clone();
put_pattern_value(&subject, quad.subject, &mut new_tuple); put_pattern_value(&subject, quad.subject, &mut new_tuple)?;
put_pattern_value(&predicate, quad.predicate, &mut new_tuple); put_pattern_value(&predicate, quad.predicate, &mut new_tuple)?;
put_pattern_value(&object, quad.object, &mut new_tuple); put_pattern_value(&object, quad.object, &mut new_tuple)?;
put_pattern_value(&graph_name, quad.graph_name, &mut new_tuple); put_pattern_value(&graph_name, quad.graph_name, &mut new_tuple)?;
Ok(new_tuple) Some(Ok(new_tuple))
}
Err(error) => Some(Err(error)),
})); }));
iter iter
})) }))
@ -228,10 +192,8 @@ impl SimpleEvaluator {
return result; return result;
}; };
match (input_subject, input_object) { match (input_subject, input_object) {
(Some(input_subject), Some(input_object)) => { (Some(input_subject), Some(input_object)) => Box::new(
let input_object = input_object.clone(); eval.eval_path_from(&path, &input_subject, &input_graph_name)
Box::new(
eval.eval_path_from(&path, input_subject, input_graph_name)
.filter_map(move |o| match o { .filter_map(move |o| match o {
Ok(o) => { Ok(o) => {
if o == input_object { if o == input_object {
@ -242,40 +204,49 @@ impl SimpleEvaluator {
} }
Err(error) => Some(Err(error)), Err(error) => Some(Err(error)),
}), }),
) ),
}
(Some(input_subject), None) => { (Some(input_subject), None) => {
let object = object.clone(); let object = object.clone();
Box::new( Box::new(
eval.eval_path_from(&path, input_subject, input_graph_name) eval.eval_path_from(&path, &input_subject, &input_graph_name)
.map(move |o| { .filter_map(move |o| match o {
Ok(o) => {
let mut new_tuple = tuple.clone(); let mut new_tuple = tuple.clone();
put_pattern_value(&object, o?, &mut new_tuple); put_pattern_value(&object, o, &mut new_tuple)?;
Ok(new_tuple) Some(Ok(new_tuple))
}
Err(error) => Some(Err(error)),
}), }),
) )
} }
(None, Some(input_object)) => { (None, Some(input_object)) => {
let subject = subject.clone(); let subject = subject.clone();
Box::new( Box::new(
eval.eval_path_to(&path, input_object, input_graph_name) eval.eval_path_to(&path, &input_object, &input_graph_name)
.map(move |s| { .filter_map(move |s| match s {
Ok(s) => {
let mut new_tuple = tuple.clone(); let mut new_tuple = tuple.clone();
put_pattern_value(&subject, s?, &mut new_tuple); put_pattern_value(&subject, s, &mut new_tuple)?;
Ok(new_tuple) Some(Ok(new_tuple))
}
Err(error) => Some(Err(error)),
}), }),
) )
} }
(None, None) => { (None, None) => {
let subject = subject.clone(); let subject = subject.clone();
let object = object.clone(); let object = object.clone();
Box::new(eval.eval_open_path(&path, input_graph_name).map(move |so| { Box::new(eval.eval_open_path(&path, &input_graph_name).filter_map(
move |so| match so {
Ok((s, o)) => {
let mut new_tuple = tuple.clone(); let mut new_tuple = tuple.clone();
let (s, o) = so?; 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); Some(Ok(new_tuple))
Ok(new_tuple) }
})) Err(error) => Some(Err(error)),
},
))
} }
} }
})) }))
@ -364,7 +335,7 @@ impl SimpleEvaluator {
Box::new(self.eval_plan(child, from).map(move |tuple| { Box::new(self.eval_plan(child, from).map(move |tuple| {
let mut tuple = tuple?; let mut tuple = tuple?;
if let Some(value) = eval.eval_expression(&expression, &tuple) { if let Some(value) = eval.eval_expression(&expression, &tuple) {
tuple.set(position, value) tuple.set(position, value);
} }
Ok(tuple) Ok(tuple)
})) }))
@ -419,7 +390,7 @@ impl SimpleEvaluator {
let mut output_tuple = EncodedTuple::with_capacity(from.capacity()); let mut output_tuple = EncodedTuple::with_capacity(from.capacity());
for (input_key, output_key) in mapping.iter() { for (input_key, output_key) in mapping.iter() {
if let Some(value) = tuple.get(*input_key) { if let Some(value) = tuple.get(*input_key) {
output_tuple.set(*output_key, value.clone()) output_tuple.set(*output_key, value.clone());
} }
} }
Ok(output_tuple) Ok(output_tuple)
@ -513,7 +484,7 @@ impl SimpleEvaluator {
let service_name = get_pattern_value(service_name, from) let service_name = get_pattern_value(service_name, from)
.ok_or_else(|| EvaluationError::msg("The SERVICE name is not bound"))?; .ok_or_else(|| EvaluationError::msg("The SERVICE name is not bound"))?;
if let QueryResults::Solutions(iter) = self.service_handler.handle( if let QueryResults::Solutions(iter) = self.service_handler.handle(
self.dataset.decode_named_node(service_name)?, self.dataset.decode_named_node(&service_name)?,
Query { Query {
inner: spargebra::Query::Select { inner: spargebra::Query::Select {
dataset: None, dataset: None,
@ -2425,17 +2396,49 @@ impl NumericBinaryOperands {
fn get_pattern_value<'a>( fn get_pattern_value<'a>(
selector: &'a PatternValue, selector: &'a PatternValue,
tuple: &'a EncodedTuple, tuple: &'a EncodedTuple,
) -> Option<&'a EncodedTerm> { ) -> Option<EncodedTerm> {
match selector { match selector {
PatternValue::Constant(term) => Some(term), PatternValue::Constant(term) => Some(term.clone()),
PatternValue::Variable(v) => tuple.get(*v), PatternValue::Variable(v) => tuple.get(*v).cloned(),
PatternValue::Triple(triple) => Some(
EncodedTriple {
subject: get_pattern_value(&triple.subject, tuple)?,
predicate: get_pattern_value(&triple.predicate, tuple)?,
object: get_pattern_value(&triple.object, tuple)?,
}
.into(),
),
} }
} }
fn put_pattern_value(selector: &PatternValue, value: EncodedTerm, tuple: &mut EncodedTuple) { fn put_pattern_value(
selector: &PatternValue,
value: EncodedTerm,
tuple: &mut EncodedTuple,
) -> Option<()> {
match selector { match selector {
PatternValue::Constant(_) => (), PatternValue::Constant(_) => Some(()),
PatternValue::Variable(v) => tuple.set(*v, value), PatternValue::Variable(v) => {
if let Some(old) = tuple.get(*v) {
if value == *old {
Some(())
} else {
None
}
} else {
tuple.set(*v, value);
Some(())
}
}
PatternValue::Triple(triple) => {
if let EncodedTerm::Triple(value) = value {
put_pattern_value(&triple.subject, value.subject.clone(), tuple)?;
put_pattern_value(&triple.predicate, value.predicate.clone(), tuple)?;
put_pattern_value(&triple.object, value.object.clone(), tuple)
} else {
None
}
}
} }
} }
@ -2669,17 +2672,15 @@ impl Iterator for ConstructIterator {
}; };
for template in &self.template { for template in &self.template {
if let (Some(subject), Some(predicate), Some(object)) = ( if let (Some(subject), Some(predicate), Some(object)) = (
get_triple_template_value(&template.subject, &tuple, &mut self.bnodes) get_triple_template_value(&template.subject, &tuple, &mut self.bnodes),
.cloned(), get_triple_template_value(&template.predicate, &tuple, &mut self.bnodes),
get_triple_template_value(&template.predicate, &tuple, &mut self.bnodes)
.cloned(),
get_triple_template_value(&template.object, &tuple, &mut self.bnodes), get_triple_template_value(&template.object, &tuple, &mut self.bnodes),
) { ) {
self.buffered_results.push(decode_triple( self.buffered_results.push(decode_triple(
&*self.eval.dataset, &*self.eval.dataset,
&subject, &subject,
&predicate, &predicate,
object, &object,
)); ));
} }
} }
@ -2693,16 +2694,24 @@ fn get_triple_template_value<'a>(
selector: &'a TripleTemplateValue, selector: &'a TripleTemplateValue,
tuple: &'a EncodedTuple, tuple: &'a EncodedTuple,
bnodes: &'a mut Vec<EncodedTerm>, bnodes: &'a mut Vec<EncodedTerm>,
) -> Option<&'a EncodedTerm> { ) -> Option<EncodedTerm> {
match selector { match selector {
TripleTemplateValue::Constant(term) => Some(term), TripleTemplateValue::Constant(term) => Some(term.clone()),
TripleTemplateValue::Variable(v) => tuple.get(*v), TripleTemplateValue::Variable(v) => tuple.get(*v).cloned(),
TripleTemplateValue::BlankNode(id) => { TripleTemplateValue::BlankNode(id) => {
if *id >= bnodes.len() { if *id >= bnodes.len() {
bnodes.resize_with(*id + 1, new_bnode) bnodes.resize_with(*id + 1, new_bnode)
} }
Some(&bnodes[*id]) Some(bnodes[*id].clone())
} }
TripleTemplateValue::Triple(triple) => Some(
EncodedTriple {
subject: get_triple_template_value(&triple.subject, tuple, bnodes)?,
predicate: get_triple_template_value(&triple.subject, tuple, bnodes)?,
object: get_triple_template_value(&triple.subject, tuple, bnodes)?,
}
.into(),
),
} }
} }

@ -197,15 +197,14 @@ impl PlanNode {
pub enum PatternValue { pub enum PatternValue {
Constant(EncodedTerm), Constant(EncodedTerm),
Variable(usize), Variable(usize),
Triple(Box<TriplePatternValue>),
} }
impl PatternValue { #[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub fn is_var(&self) -> bool { pub struct TriplePatternValue {
match self { pub subject: PatternValue,
PatternValue::Constant(_) => false, pub predicate: PatternValue,
PatternValue::Variable(_) => true, pub object: PatternValue,
}
}
} }
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Hash)]
@ -486,6 +485,7 @@ pub enum TripleTemplateValue {
Constant(EncodedTerm), Constant(EncodedTerm),
BlankNode(usize), BlankNode(usize),
Variable(usize), Variable(usize),
Triple(Box<TripleTemplate>),
} }
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Hash)]

@ -807,7 +807,33 @@ impl<'a> PlanBuilder<'a> {
//TODO: very bad hack to convert bnode to variable //TODO: very bad hack to convert bnode to variable
} }
TermPattern::Literal(literal) => PatternValue::Constant(self.build_literal(literal)?), TermPattern::Literal(literal) => PatternValue::Constant(self.build_literal(literal)?),
TermPattern::Triple(_) => unimplemented!(), TermPattern::Triple(triple) => {
match (
self.pattern_value_from_term_or_variable(&triple.subject, variables)?,
self.pattern_value_from_named_node_or_variable(&triple.predicate, variables)?,
self.pattern_value_from_term_or_variable(&triple.object, variables)?,
) {
(
PatternValue::Constant(subject),
PatternValue::Constant(predicate),
PatternValue::Constant(object),
) => PatternValue::Constant(
EncodedTriple {
subject,
predicate,
object,
}
.into(),
),
(subject, predicate, object) => {
PatternValue::Triple(Box::new(TriplePatternValue {
subject,
predicate,
object,
}))
}
}
}
}) })
} }
@ -959,7 +985,31 @@ impl<'a> PlanBuilder<'a> {
TermPattern::Literal(literal) => { TermPattern::Literal(literal) => {
TripleTemplateValue::Constant(self.build_literal(literal)?) TripleTemplateValue::Constant(self.build_literal(literal)?)
} }
TermPattern::Triple(_) => unimplemented!(), TermPattern::Triple(triple) => match (
self.template_value_from_term_or_variable(&triple.subject, variables, bnodes)?,
self.template_value_from_named_node_or_variable(&triple.predicate, variables)?,
self.template_value_from_term_or_variable(&triple.object, variables, bnodes)?,
) {
(
TripleTemplateValue::Constant(subject),
TripleTemplateValue::Constant(predicate),
TripleTemplateValue::Constant(object),
) => TripleTemplateValue::Constant(
EncodedTriple {
subject,
predicate,
object,
}
.into(),
),
(subject, predicate, object) => {
TripleTemplateValue::Triple(Box::new(TripleTemplate {
subject,
predicate,
object,
}))
}
},
}) })
} }
@ -989,6 +1039,11 @@ impl<'a> PlanBuilder<'a> {
PatternValue::Variable(from_id) => { PatternValue::Variable(from_id) => {
PatternValue::Variable(self.convert_variable_id(*from_id, from, to)) PatternValue::Variable(self.convert_variable_id(*from_id, from, to))
} }
PatternValue::Triple(triple) => PatternValue::Triple(Box::new(TriplePatternValue {
subject: self.convert_pattern_value_id(&triple.subject, from, to),
predicate: self.convert_pattern_value_id(&triple.predicate, from, to),
object: self.convert_pattern_value_id(&triple.object, from, to),
})),
} }
} }

Loading…
Cancel
Save