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. 126
      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::StaticBindings { tuples } => Box::new(tuples.iter().cloned().map(Ok)),
PlanNode::Service {
child,
variables,
silent,
service_name,
graph_pattern,
..
} => {
println!("Service!");
self.eval_plan(&*child, from, options)
match &options.service_handler {
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 {
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)]
fn equals(&self, a: EncodedTerm, b: EncodedTerm) -> Option<bool> {
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) {
if position < tuple.len() {
tuple[position] = Some(value)

@ -188,6 +188,12 @@ impl<'a> QueryOptions<'a> {
self.default_graph_as_union = true;
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/)

@ -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 results = prepared_query.exec(&query_options).unwrap();
if let QueryResult::Bindings(results) = results {
@ -107,73 +107,78 @@ fn simple_service_test() {
assert_eq!(true, false);
}
}
/*
#[derive(Clone,Copy)]
struct TwoServiceTest;
impl ServiceHandler for TwoServiceTest {
fn handle<'a>(&'a self, named_node: NamedNode) -> Option<(fn(GraphPattern) -> Result<BindingsIterator<'a>>)> {
println!("Handler called for {:?}", named_node);
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<BindingsIterator<'a>> {
let repository = MemoryRepository::default();
let mut connection = repository.connection().unwrap();
let file = 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" .
"#;
connection.load_graph(file.as_ref(), GraphSyntax::NTriples, None, None).unwrap();
let prepared_query = connection.prepare_query_from_pattern(&graph_pattern, None).unwrap();
let result = prepared_query.exec(&Some(NoneService)).unwrap();
match result {
QueryResult::Bindings(iterator) => {
let (variables, iter) = iterator.destruct();
let cloned_iter = iter.collect::<Vec<_>>().into_iter();
let new_iter = BindingsIterator::new(variables, Box::new(cloned_iter));
Ok(new_iter)
},
_ => Err(format_err!("Excpected bindings but got another QueryResult"))
}
}
#[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>>)> {
println!("Handler called for {:?}", named_node);
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}
}
}
fn handle_service2<'a>(graph_pattern: GraphPattern) -> Result<BindingsIterator<'a>> {
let repository = MemoryRepository::default();
let mut connection = repository.connection().unwrap();
let file = 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> .
"#;
connection.load_graph(file.as_ref(), GraphSyntax::NTriples, None, None).unwrap();
let prepared_query = connection.prepare_query_from_pattern(&graph_pattern, None).unwrap();
let result = prepared_query.exec(&Some(NoneService)).unwrap();
match result {
QueryResult::Bindings(iterator) => {
let (variables, iter) = iterator.destruct();
let cloned_iter = iter.collect::<Vec<_>>().into_iter();
let new_iter = BindingsIterator::new(variables, Box::new(cloned_iter));
Ok(new_iter)
},
_ => Err(format_err!("Excpected bindings but got another QueryResult"))
impl TwoServiceTest {
fn handle_service1<'a>(graph_pattern: GraphPattern) -> Result<BindingsIterator<'a>> {
let repository = MemoryRepository::default();
let mut connection = repository.connection().unwrap();
let file = 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" .
"#;
connection.load_graph(file.as_ref(), GraphSyntax::NTriples, None, None).unwrap();
let query_options = QueryOptions::default().with_service_handler(Box::new(TwoServiceTest));
let prepared_query = connection.prepare_query_from_pattern(&graph_pattern, &query_options).unwrap();
let result = prepared_query.exec(&query_options).unwrap();
match result {
QueryResult::Bindings(iterator) => {
let (variables, iter) = iterator.destruct();
let cloned_iter = iter.collect::<Vec<_>>().into_iter();
let new_iter = BindingsIterator::new(variables, Box::new(cloned_iter));
Ok(new_iter)
},
_ => Err(format_err!("Excpected bindings but got another QueryResult"))
}
}
}
}
#[test]
fn two_service_test() {
fn handle_service2<'a>(graph_pattern: GraphPattern) -> Result<BindingsIterator<'a>> {
let repository = MemoryRepository::default();
let mut connection = repository.connection().unwrap();
let file = 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> .
"#;
connection.load_graph(file.as_ref(), GraphSyntax::NTriples, None, None).unwrap();
let query_options = QueryOptions::default().with_service_handler(Box::new(TwoServiceTest));
let prepared_query = connection.prepare_query_from_pattern(&graph_pattern, &query_options).unwrap();
let result = prepared_query.exec(&query_options).unwrap();
match result {
QueryResult::Bindings(iterator) => {
let (variables, iter) = iterator.destruct();
let cloned_iter = iter.collect::<Vec<_>>().into_iter();
let new_iter = BindingsIterator::new(variables, Box::new(cloned_iter));
Ok(new_iter)
},
_ => Err(format_err!("Excpected bindings but got another QueryResult"))
}
}
}
let repository = MemoryRepository::default();
let connection = repository.connection().unwrap();
@ -193,9 +198,9 @@ fn two_service_test() {
ORDER BY ?name
"#;
let prepared_query = connection.prepare_query(query, None).unwrap();
let service_handler = Some(TwoServiceTest);
let results = prepared_query.exec(&service_handler).unwrap();
let query_options = QueryOptions::default().with_service_handler(Box::new(TwoServiceTest));
let prepared_query = connection.prepare_query(query, &query_options).unwrap();
let results = prepared_query.exec(&query_options).unwrap();
if let QueryResult::Bindings(results) = results {
let collected = results.into_values_iter().map(move |b| b.unwrap()).collect::<Vec<_>>();
for c in collected.clone() {
@ -212,6 +217,5 @@ fn two_service_test() {
assert_eq!(true, false);
}
}
*/

Loading…
Cancel
Save