pull/11/head
Dustin Whitney 5 years ago
parent 68d067259c
commit 9d83649a08
  1. 100
      lib/src/sparql/eval.rs
  2. 6
      lib/src/sparql/mod.rs
  3. 30
      lib/tests/service_test_cases.rs

@ -131,11 +131,56 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
PlanNode::Init => Box::new(once(Ok(from))), PlanNode::Init => Box::new(once(Ok(from))),
PlanNode::StaticBindings { tuples } => Box::new(tuples.iter().cloned().map(Ok)), PlanNode::StaticBindings { tuples } => Box::new(tuples.iter().cloned().map(Ok)),
PlanNode::Service { PlanNode::Service {
child, variables,
silent,
service_name,
graph_pattern,
.. ..
} => { } => {
println!("Service!"); match &options.service_handler {
self.eval_plan(&*child, from, options) None => if *silent {
return Box::new(vec![].into_iter());
} 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(vec![].into_iter());
} else {
return Box::new(once(Err(format_err!(
"The handler supplied was unable to evaluate the given service"
)))) as EncodedTuplesIterator<'_>;
},
Some(term) => {
let named_node = self.dataset.decode_named_node(term).unwrap();
handler.handle(named_node)
},
};
match pattern_option {
None => if *silent {
return Box::new(vec![].into_iter());
} 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) => {
let bindings = pattern_fn(graph_pattern.clone()).unwrap();
let encoded = self.encode_bindings(variables, bindings);
let collected = encoded.collect::<Vec<_>>();
Box::new(JoinIterator {
left: vec![from],
right_iter: Box::new(collected.into_iter()),
buffered_results: vec![],
})
},
}
}
}
}, },
PlanNode::QuadPatternJoin { PlanNode::QuadPatternJoin {
child, child,
@ -1589,6 +1634,45 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
) )
} }
fn encode_bindings<'b>(
&'b self,
variables: &'b [Variable],
iter: BindingsIterator<'b>,
) -> EncodedTuplesIterator<'b>
where
'a: 'b,
{
let mut encoder = self.dataset.encoder();
let (binding_variables, iter) = BindingsIterator::destruct(iter);
let mut combined_variables = variables.clone().to_vec();
for v in binding_variables.clone() {
if !combined_variables.contains(&v) {
combined_variables.resize(combined_variables.len() + 1, v);
}
}
println!("binding_variables: {:?}", binding_variables.clone());
println!("variables: {:?}", variables.clone());
println!("combined_variables: {:?}", combined_variables.clone());
println!("\n\n");
Box::new(iter.map(move |terms| {
let mut encoded_terms = vec![None; combined_variables.len()];
for (i, term_option) in terms?.into_iter().enumerate() {
match term_option {
None => (),
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)
}
}
}
}
Ok(encoded_terms)
}))
}
#[allow(clippy::float_cmp)] #[allow(clippy::float_cmp)]
fn equals(&self, a: EncodedTerm, b: EncodedTerm) -> Option<bool> { fn equals(&self, a: EncodedTerm, b: EncodedTerm) -> Option<bool> {
match a { match a {
@ -1963,6 +2047,16 @@ fn put_pattern_value(selector: &PatternValue, value: EncodedTerm, tuple: &mut En
} }
} }
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);
break;
}
}
}
fn put_value(position: usize, value: EncodedTerm, tuple: &mut EncodedTuple) { fn put_value(position: usize, value: EncodedTerm, tuple: &mut EncodedTuple) {
if position < tuple.len() { if position < tuple.len() {
tuple[position] = Some(value) tuple[position] = Some(value)

@ -188,6 +188,12 @@ impl<'a> QueryOptions<'a> {
self.default_graph_as_union = true; self.default_graph_as_union = true;
self self
} }
/// Consider the union of all graphs in the repository as the default graph
pub fn with_service_handler(mut self, service_handler: Box<dyn ServiceHandler>) -> Self {
self.service_handler = Some(service_handler);
self
}
} }
/// A parsed [SPARQL query](https://www.w3.org/TR/sparql11-query/) /// A parsed [SPARQL query](https://www.w3.org/TR/sparql11-query/)

@ -94,7 +94,7 @@ fn simple_service_test() {
"#; "#;
let query_options = QueryOptions::default(); let query_options = QueryOptions::default().with_service_handler(Box::new(TestServiceHandler));
let prepared_query = connection.prepare_query(query, &query_options).unwrap(); let prepared_query = connection.prepare_query(query, &query_options).unwrap();
let results = prepared_query.exec(&query_options).unwrap(); let results = prepared_query.exec(&query_options).unwrap();
if let QueryResult::Bindings(results) = results { if let QueryResult::Bindings(results) = results {
@ -107,7 +107,13 @@ fn simple_service_test() {
assert_eq!(true, false); assert_eq!(true, false);
} }
} }
/*
#[test]
fn two_service_test() {
#[derive(Clone,Copy)] #[derive(Clone,Copy)]
struct TwoServiceTest; struct TwoServiceTest;
impl ServiceHandler for TwoServiceTest { impl ServiceHandler for TwoServiceTest {
@ -132,8 +138,9 @@ impl TwoServiceTest {
<http://example.com/alice> <http://xmlns.com/foaf/0.1/name> "Alice" . <http://example.com/alice> <http://xmlns.com/foaf/0.1/name> "Alice" .
"#; "#;
connection.load_graph(file.as_ref(), GraphSyntax::NTriples, None, None).unwrap(); connection.load_graph(file.as_ref(), GraphSyntax::NTriples, None, None).unwrap();
let prepared_query = connection.prepare_query_from_pattern(&graph_pattern, None).unwrap(); let query_options = QueryOptions::default().with_service_handler(Box::new(TwoServiceTest));
let result = prepared_query.exec(&Some(NoneService)).unwrap(); let prepared_query = connection.prepare_query_from_pattern(&graph_pattern, &query_options).unwrap();
let result = prepared_query.exec(&query_options).unwrap();
match result { match result {
QueryResult::Bindings(iterator) => { QueryResult::Bindings(iterator) => {
let (variables, iter) = iterator.destruct(); let (variables, iter) = iterator.destruct();
@ -156,8 +163,9 @@ impl TwoServiceTest {
<http://example.com/alice> <http://xmlns.com/foaf/0.1/mbox> <mailto:alice@example.com> . <http://example.com/alice> <http://xmlns.com/foaf/0.1/mbox> <mailto:alice@example.com> .
"#; "#;
connection.load_graph(file.as_ref(), GraphSyntax::NTriples, None, None).unwrap(); connection.load_graph(file.as_ref(), GraphSyntax::NTriples, None, None).unwrap();
let prepared_query = connection.prepare_query_from_pattern(&graph_pattern, None).unwrap(); let query_options = QueryOptions::default().with_service_handler(Box::new(TwoServiceTest));
let result = prepared_query.exec(&Some(NoneService)).unwrap(); let prepared_query = connection.prepare_query_from_pattern(&graph_pattern, &query_options).unwrap();
let result = prepared_query.exec(&query_options).unwrap();
match result { match result {
QueryResult::Bindings(iterator) => { QueryResult::Bindings(iterator) => {
let (variables, iter) = iterator.destruct(); let (variables, iter) = iterator.destruct();
@ -171,9 +179,6 @@ impl TwoServiceTest {
} }
#[test]
fn two_service_test() {
let repository = MemoryRepository::default(); let repository = MemoryRepository::default();
let connection = repository.connection().unwrap(); let connection = repository.connection().unwrap();
@ -193,9 +198,9 @@ fn two_service_test() {
ORDER BY ?name ORDER BY ?name
"#; "#;
let prepared_query = connection.prepare_query(query, None).unwrap(); let query_options = QueryOptions::default().with_service_handler(Box::new(TwoServiceTest));
let service_handler = Some(TwoServiceTest); let prepared_query = connection.prepare_query(query, &query_options).unwrap();
let results = prepared_query.exec(&service_handler).unwrap(); let results = prepared_query.exec(&query_options).unwrap();
if let QueryResult::Bindings(results) = results { if let QueryResult::Bindings(results) = results {
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<_>>();
for c in collected.clone() { for c in collected.clone() {
@ -212,6 +217,5 @@ fn two_service_test() {
assert_eq!(true, false); assert_eq!(true, false);
} }
} }
*/

Loading…
Cancel
Save