Merge pull request #12 from Tpt/service-improvements

Service support improvements
pull/14/head
Thomas Tanon 5 years ago committed by GitHub
commit 33ecea643c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      lib/src/lib.rs
  2. 26
      lib/src/repository.rs
  3. 872
      lib/src/sparql/eval.rs
  4. 83
      lib/src/sparql/mod.rs
  5. 11
      lib/src/sparql/plan.rs
  6. 7
      lib/src/sparql/plan_builder.rs
  7. 5
      lib/src/store/memory.rs
  8. 18
      lib/src/store/mod.rs
  9. 5
      lib/src/store/rocksdb.rs
  10. 34
      lib/tests/service_test_cases.rs
  11. 4
      lib/tests/sparql_test_cases.rs
  12. 5
      server/src/main.rs

@ -27,9 +27,8 @@
//! assert_eq!(vec![quad], results.unwrap()); //! assert_eq!(vec![quad], results.unwrap());
//! //!
//! // SPARQL query //! // SPARQL query
//! let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }", None).unwrap(); //! let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default()).unwrap();
//! let options = QueryOptions::default(); //! let results = prepared_query.exec().unwrap();
//! let results = prepared_query.exec(&options).unwrap();
//! if let QueryResult::Bindings(results) = results { //! if let QueryResult::Bindings(results) = results {
//! assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into())); //! assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into()));
//! } //! }

@ -1,5 +1,5 @@
use crate::model::*; use crate::model::*;
use crate::sparql::{GraphPattern, PreparedQuery}; use crate::sparql::{GraphPattern, PreparedQuery, QueryOptions};
use crate::{DatasetSyntax, GraphSyntax, Result}; use crate::{DatasetSyntax, GraphSyntax, Result};
use std::io::BufRead; use std::io::BufRead;
@ -30,9 +30,8 @@ use std::io::BufRead;
/// assert_eq!(vec![quad], results.unwrap()); /// assert_eq!(vec![quad], results.unwrap());
/// ///
/// // SPARQL query /// // SPARQL query
/// let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }", None).unwrap(); /// let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default()).unwrap();
/// let options = QueryOptions::default(); /// let results = prepared_query.exec().unwrap();
/// let results = prepared_query.exec(&options).unwrap();
/// if let QueryResult::Bindings(results) = results { /// if let QueryResult::Bindings(results) = results {
/// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into())); /// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into()));
/// } /// }
@ -76,24 +75,19 @@ pub trait RepositoryConnection: Clone {
/// connection.insert(&Quad::new(ex.clone(), ex.clone(), ex.clone(), None)); /// connection.insert(&Quad::new(ex.clone(), ex.clone(), ex.clone(), None));
/// ///
/// // SPARQL query /// // SPARQL query
/// let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }", None).unwrap(); /// let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default()).unwrap();
/// let options = QueryOptions::default(); /// let results = prepared_query.exec().unwrap();
/// let results = prepared_query.exec(&options).unwrap();
/// if let QueryResult::Bindings(results) = results { /// if let QueryResult::Bindings(results) = results {
/// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into())); /// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into()));
/// } /// }
/// ``` /// ```
fn prepare_query<'a>( fn prepare_query(&self, query: &str, options: QueryOptions) -> Result<Self::PreparedQuery>;
&'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. /// 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>( fn prepare_query_from_pattern(
&'a self, &self,
graph_pattern: &'a GraphPattern, graph_pattern: &GraphPattern,
base_iri: Option<&str>, options: QueryOptions,
) -> Result<Self::PreparedQuery>; ) -> Result<Self::PreparedQuery>;
/// Retrieves quads with a filter on each quad component /// Retrieves quads with a filter on each quad component

File diff suppressed because it is too large Load Diff

@ -18,7 +18,6 @@ use crate::sparql::plan::{DatasetView, PlanNode};
use crate::sparql::plan_builder::PlanBuilder; use crate::sparql::plan_builder::PlanBuilder;
use crate::store::StoreConnection; use crate::store::StoreConnection;
use crate::Result; use crate::Result;
use failure::format_err;
use rio_api::iri::Iri; use rio_api::iri::Iri;
use std::fmt; use std::fmt;
@ -31,7 +30,7 @@ pub use crate::sparql::model::Variable;
/// A prepared [SPARQL query](https://www.w3.org/TR/sparql11-query/) /// A prepared [SPARQL query](https://www.w3.org/TR/sparql11-query/)
pub trait PreparedQuery { pub trait PreparedQuery {
/// Evaluates the query and returns its results /// Evaluates the query and returns its results
fn exec<'a>(&'a self, options: &'a QueryOptions<'a>) -> Result<QueryResult<'a>>; fn exec(&self) -> Result<QueryResult>;
} }
/// An implementation of `PreparedQuery` for internal use /// An implementation of `PreparedQuery` for internal use
@ -59,10 +58,9 @@ enum SimplePreparedQueryAction<S: StoreConnection> {
} }
impl<'a, S: StoreConnection + 'a> SimplePreparedQuery<S> { impl<'a, S: StoreConnection + 'a> SimplePreparedQuery<S> {
pub(crate) fn new(connection: S, query: &str, base_iri: Option<&'a str>) -> Result<Self> { pub(crate) fn new(connection: S, query: &str, options: QueryOptions) -> Result<Self> {
let dataset = DatasetView::new(connection); let dataset = DatasetView::new(connection, options.default_graph_as_union);
//TODO avoid inserting terms in the Repository StringStore Ok(Self(match read_sparql_query(query, options.base_iri)? {
Ok(Self(match read_sparql_query(query, base_iri)? {
QueryVariants::Select { QueryVariants::Select {
algebra, algebra,
dataset: _, dataset: _,
@ -72,7 +70,7 @@ impl<'a, S: StoreConnection + 'a> SimplePreparedQuery<S> {
SimplePreparedQueryAction::Select { SimplePreparedQueryAction::Select {
plan, plan,
variables, variables,
evaluator: SimpleEvaluator::new(dataset, base_iri), evaluator: SimpleEvaluator::new(dataset, base_iri, options.service_handler),
} }
} }
QueryVariants::Ask { QueryVariants::Ask {
@ -83,7 +81,7 @@ impl<'a, S: StoreConnection + 'a> SimplePreparedQuery<S> {
let (plan, _) = PlanBuilder::build(dataset.encoder(), &algebra)?; let (plan, _) = PlanBuilder::build(dataset.encoder(), &algebra)?;
SimplePreparedQueryAction::Ask { SimplePreparedQueryAction::Ask {
plan, plan,
evaluator: SimpleEvaluator::new(dataset, base_iri), evaluator: SimpleEvaluator::new(dataset, base_iri, options.service_handler),
} }
} }
QueryVariants::Construct { QueryVariants::Construct {
@ -100,7 +98,7 @@ impl<'a, S: StoreConnection + 'a> SimplePreparedQuery<S> {
&construct, &construct,
variables, variables,
)?, )?,
evaluator: SimpleEvaluator::new(dataset, base_iri), evaluator: SimpleEvaluator::new(dataset, base_iri, options.service_handler),
} }
} }
QueryVariants::Describe { QueryVariants::Describe {
@ -111,7 +109,7 @@ impl<'a, S: StoreConnection + 'a> SimplePreparedQuery<S> {
let (plan, _) = PlanBuilder::build(dataset.encoder(), &algebra)?; let (plan, _) = PlanBuilder::build(dataset.encoder(), &algebra)?;
SimplePreparedQueryAction::Describe { SimplePreparedQueryAction::Describe {
plan, plan,
evaluator: SimpleEvaluator::new(dataset, base_iri), evaluator: SimpleEvaluator::new(dataset, base_iri, options.service_handler),
} }
} }
})) }))
@ -121,62 +119,77 @@ impl<'a, S: StoreConnection + 'a> SimplePreparedQuery<S> {
pub(crate) fn new_from_pattern( pub(crate) fn new_from_pattern(
connection: S, connection: S,
pattern: &GraphPattern, pattern: &GraphPattern,
base_iri: Option<&'a str>, options: QueryOptions,
) -> Result<Self> { ) -> Result<Self> {
let dataset = DatasetView::new(connection); let dataset = DatasetView::new(connection, options.default_graph_as_union);
let (plan, variables) = PlanBuilder::build(dataset.encoder(), pattern)?; let (plan, variables) = PlanBuilder::build(dataset.encoder(), pattern)?;
let base_iri = base_iri.map(|str_iri| Iri::parse(str_iri.to_string())); let base_iri = if let Some(base_iri) = options.base_iri {
match base_iri { Some(Iri::parse(base_iri.to_string())?)
Some(Err(_)) => Err(format_err!("Failed to parse base_iri")), } else {
Some(Ok(base_iri)) => Ok(Self(SimplePreparedQueryAction::Select { None
plan, };
variables, Ok(Self(SimplePreparedQueryAction::Select {
evaluator: SimpleEvaluator::new(dataset, Some(base_iri)), plan,
})), variables,
None => Ok(Self(SimplePreparedQueryAction::Select { evaluator: SimpleEvaluator::new(dataset, base_iri, options.service_handler),
plan, }))
variables,
evaluator: SimpleEvaluator::new(dataset, None),
})),
}
} }
} }
impl<S: StoreConnection> PreparedQuery for SimplePreparedQuery<S> { impl<S: StoreConnection> PreparedQuery for SimplePreparedQuery<S> {
fn exec<'a>(&'a self, options: &'a QueryOptions<'a>) -> Result<QueryResult<'a>> { fn exec(&self) -> Result<QueryResult> {
match &self.0 { match &self.0 {
SimplePreparedQueryAction::Select { SimplePreparedQueryAction::Select {
plan, plan,
variables, variables,
evaluator, evaluator,
} => evaluator.evaluate_select_plan(&plan, &variables, options), } => evaluator.evaluate_select_plan(&plan, &variables),
SimplePreparedQueryAction::Ask { plan, evaluator } => { SimplePreparedQueryAction::Ask { plan, evaluator } => {
evaluator.evaluate_ask_plan(&plan, options) evaluator.evaluate_ask_plan(&plan)
} }
SimplePreparedQueryAction::Construct { SimplePreparedQueryAction::Construct {
plan, plan,
construct, construct,
evaluator, evaluator,
} => evaluator.evaluate_construct_plan(&plan, &construct, &options), } => evaluator.evaluate_construct_plan(&plan, &construct),
SimplePreparedQueryAction::Describe { plan, evaluator } => { SimplePreparedQueryAction::Describe { plan, evaluator } => {
evaluator.evaluate_describe_plan(&plan, &options) evaluator.evaluate_describe_plan(&plan)
} }
} }
} }
} }
/// Handler for SPARQL SERVICEs.
///
/// Might be used to implement [SPARQL 1.1 Federated Query](https://www.w3.org/TR/sparql11-federated-query/)
pub trait ServiceHandler { pub trait ServiceHandler {
/// Get the handler for a given service identified by a RDF IRI.
///
/// A service is a function that returns an iterator of bindings from a `GraphPattern`.
/// Returns `None` if there is no handler for the service.
fn handle<'a>( fn handle<'a>(
&'a self, &'a self,
node: NamedNode, node: &NamedNode,
) -> Option<(fn(GraphPattern) -> Result<BindingsIterator<'a>>)>; ) -> Option<(fn(GraphPattern) -> Result<BindingsIterator<'a>>)>;
} }
#[derive(Default)]
struct EmptyServiceHandler {}
impl ServiceHandler for EmptyServiceHandler {
fn handle(
&self,
_node: &NamedNode,
) -> Option<(fn(GraphPattern) -> Result<BindingsIterator<'static>>)> {
None
}
}
/// Options for SPARQL query parsing and evaluation like the query base IRI /// Options for SPARQL query parsing and evaluation like the query base IRI
pub struct QueryOptions<'a> { pub struct QueryOptions<'a> {
pub(crate) base_iri: Option<&'a str>, pub(crate) base_iri: Option<&'a str>,
pub(crate) default_graph_as_union: bool, pub(crate) default_graph_as_union: bool,
pub(crate) service_handler: Option<Box<dyn ServiceHandler>>, pub(crate) service_handler: Box<dyn ServiceHandler>,
} }
impl<'a> Default for QueryOptions<'a> { impl<'a> Default for QueryOptions<'a> {
@ -184,7 +197,7 @@ impl<'a> Default for QueryOptions<'a> {
Self { Self {
base_iri: None, base_iri: None,
default_graph_as_union: false, default_graph_as_union: false,
service_handler: None as Option<Box<dyn ServiceHandler>>, service_handler: Box::new(EmptyServiceHandler::default()),
} }
} }
} }
@ -204,7 +217,7 @@ impl<'a> QueryOptions<'a> {
/// Consider the union of all graphs in the repository as the default graph /// 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 { pub fn with_service_handler(mut self, service_handler: Box<dyn ServiceHandler>) -> Self {
self.service_handler = Some(service_handler); self.service_handler = service_handler;
self self
} }
} }

@ -22,7 +22,7 @@ pub enum PlanNode {
service_name: PatternValue, service_name: PatternValue,
variables: Vec<Variable>, variables: Vec<Variable>,
child: Box<PlanNode>, child: Box<PlanNode>,
graph_pattern: GraphPattern, graph_pattern: Box<GraphPattern>,
silent: bool, silent: bool,
}, },
QuadPatternJoin { QuadPatternJoin {
@ -175,7 +175,7 @@ impl PlanNode {
PlanNode::HashDeduplicate { child } => child.add_variables(set), PlanNode::HashDeduplicate { child } => child.add_variables(set),
PlanNode::Skip { child, .. } => child.add_variables(set), PlanNode::Skip { child, .. } => child.add_variables(set),
PlanNode::Limit { child, .. } => child.add_variables(set), PlanNode::Limit { child, .. } => child.add_variables(set),
PlanNode::Project { child: _, mapping } => { PlanNode::Project { mapping, .. } => {
for i in 0..mapping.len() { for i in 0..mapping.len() {
set.insert(i); set.insert(i);
} }
@ -473,13 +473,15 @@ pub enum TripleTemplateValue {
pub struct DatasetView<S: StoreConnection> { pub struct DatasetView<S: StoreConnection> {
store: S, store: S,
extra: RefCell<MemoryStrStore>, extra: RefCell<MemoryStrStore>,
default_graph_as_union: bool,
} }
impl<S: StoreConnection> DatasetView<S> { impl<S: StoreConnection> DatasetView<S> {
pub fn new(store: S) -> Self { pub fn new(store: S, default_graph_as_union: bool) -> Self {
Self { Self {
store, store,
extra: RefCell::new(MemoryStrStore::default()), extra: RefCell::new(MemoryStrStore::default()),
default_graph_as_union,
} }
} }
@ -489,7 +491,6 @@ impl<S: StoreConnection> DatasetView<S> {
predicate: Option<EncodedTerm>, predicate: Option<EncodedTerm>,
object: Option<EncodedTerm>, object: Option<EncodedTerm>,
graph_name: Option<EncodedTerm>, graph_name: Option<EncodedTerm>,
default_graph_as_union: bool,
) -> Box<dyn Iterator<Item = Result<EncodedQuad>> + 'a> { ) -> Box<dyn Iterator<Item = Result<EncodedQuad>> + 'a> {
if graph_name == None { if graph_name == None {
Box::new( Box::new(
@ -500,7 +501,7 @@ impl<S: StoreConnection> DatasetView<S> {
Ok(quad) => quad.graph_name != ENCODED_DEFAULT_GRAPH, Ok(quad) => quad.graph_name != ENCODED_DEFAULT_GRAPH,
}), }),
) )
} else if graph_name == Some(ENCODED_DEFAULT_GRAPH) && default_graph_as_union { } else if graph_name == Some(ENCODED_DEFAULT_GRAPH) && self.default_graph_as_union {
Box::new( Box::new(
self.store self.store
.quads_for_pattern(subject, predicate, object, None) .quads_for_pattern(subject, predicate, object, None)

@ -104,13 +104,14 @@ impl<E: Encoder> PlanBuilder<E> {
right: Box::new(self.build_for_graph_pattern(b, variables, graph_name)?), right: Box::new(self.build_for_graph_pattern(b, variables, graph_name)?),
}, },
GraphPattern::Service(n, p, s) => { GraphPattern::Service(n, p, s) => {
// Child building should be at the begging in order for `variables` to be filled
let child = self.build_for_graph_pattern(p, variables, graph_name)?;
let service_name = self.pattern_value_from_named_node_or_variable(n, variables)?; let service_name = self.pattern_value_from_named_node_or_variable(n, variables)?;
let graph_pattern = *p.clone();
PlanNode::Service { PlanNode::Service {
service_name, service_name,
variables: variables.clone(), variables: variables.clone(),
child: Box::new(self.build_for_graph_pattern(p, variables, service_name)?), child: Box::new(child),
graph_pattern, graph_pattern: Box::new(*p.clone()),
silent: *s, silent: *s,
} }
} }

@ -29,9 +29,8 @@ use std::sync::{PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard};
/// assert_eq!(vec![quad], results.unwrap()); /// assert_eq!(vec![quad], results.unwrap());
/// ///
/// // SPARQL query /// // SPARQL query
/// let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }", None).unwrap(); /// let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default()).unwrap();
/// let options = QueryOptions::default(); /// let results = prepared_query.exec().unwrap();
/// let results = prepared_query.exec(&options).unwrap();
/// if let QueryResult::Bindings(results) = results { /// if let QueryResult::Bindings(results) = results {
/// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into())); /// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into()));
/// } /// }

@ -11,7 +11,7 @@ pub use crate::store::memory::MemoryRepository;
pub use crate::store::rocksdb::RocksDbRepository; pub use crate::store::rocksdb::RocksDbRepository;
use crate::model::*; use crate::model::*;
use crate::sparql::SimplePreparedQuery; use crate::sparql::{QueryOptions, SimplePreparedQuery};
use crate::store::numeric_encoder::*; use crate::store::numeric_encoder::*;
use crate::{DatasetSyntax, GraphSyntax, RepositoryConnection, Result}; use crate::{DatasetSyntax, GraphSyntax, RepositoryConnection, Result};
use rio_api::parser::{QuadsParser, TriplesParser}; use rio_api::parser::{QuadsParser, TriplesParser};
@ -72,12 +72,8 @@ impl<S: StoreConnection> From<S> for StoreRepositoryConnection<S> {
impl<S: StoreConnection> RepositoryConnection for StoreRepositoryConnection<S> { impl<S: StoreConnection> RepositoryConnection for StoreRepositoryConnection<S> {
type PreparedQuery = SimplePreparedQuery<S>; type PreparedQuery = SimplePreparedQuery<S>;
fn prepare_query<'a>( fn prepare_query(&self, query: &str, options: QueryOptions) -> Result<SimplePreparedQuery<S>> {
&self, SimplePreparedQuery::new(self.inner.clone(), query, options) //TODO: avoid clone
query: &str,
base_iri: Option<&'a str>,
) -> Result<SimplePreparedQuery<S>> {
SimplePreparedQuery::new(self.inner.clone(), query, base_iri) //TODO: avoid clone
} }
fn quads_for_pattern<'a>( fn quads_for_pattern<'a>(
@ -101,12 +97,12 @@ impl<S: StoreConnection> RepositoryConnection for StoreRepositoryConnection<S> {
) )
} }
fn prepare_query_from_pattern<'a>( fn prepare_query_from_pattern(
&'a self, &self,
pattern: &GraphPattern, pattern: &GraphPattern,
base_iri: Option<&'a str>, options: QueryOptions,
) -> Result<Self::PreparedQuery> { ) -> Result<Self::PreparedQuery> {
SimplePreparedQuery::new_from_pattern(self.inner.clone(), pattern, base_iri) SimplePreparedQuery::new_from_pattern(self.inner.clone(), pattern, options)
//TODO: avoid clone //TODO: avoid clone
} }

@ -40,9 +40,8 @@ use std::str;
/// assert_eq!(vec![quad], results.unwrap()); /// assert_eq!(vec![quad], results.unwrap());
/// ///
/// // SPARQL query /// // SPARQL query
/// let options = QueryOptions::default(); /// let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default()).unwrap();
/// let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }", None).unwrap(); /// let results = prepared_query.exec().unwrap();
/// let results = prepared_query.exec(&options).unwrap();
/// if let QueryResult::Bindings(results) = results { /// if let QueryResult::Bindings(results) = results {
/// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into())); /// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into()));
/// } /// }

@ -12,7 +12,7 @@ fn simple_service_test() {
impl ServiceHandler for TestServiceHandler { impl ServiceHandler for TestServiceHandler {
fn handle<'a>( fn handle<'a>(
&'a self, &'a self,
_named_node: NamedNode, _named_node: &NamedNode,
) -> Option<(fn(GraphPattern) -> Result<BindingsIterator<'a>>)> { ) -> Option<(fn(GraphPattern) -> Result<BindingsIterator<'a>>)> {
fn pattern_handler<'a>(graph_pattern: GraphPattern) -> Result<BindingsIterator<'a>> { fn pattern_handler<'a>(graph_pattern: GraphPattern) -> Result<BindingsIterator<'a>> {
let triples = let triples =
@ -56,13 +56,13 @@ fn two_service_test() {
impl ServiceHandler for TwoServiceTest { impl ServiceHandler for TwoServiceTest {
fn handle<'a>( fn handle<'a>(
&'a self, &'a self,
named_node: NamedNode, named_node: &NamedNode,
) -> Option<(fn(GraphPattern) -> Result<BindingsIterator<'a>>)> { ) -> Option<(fn(GraphPattern) -> Result<BindingsIterator<'a>>)> {
let service1 = NamedNode::parse("http://service1.org").unwrap(); let service1 = NamedNode::parse("http://service1.org").unwrap();
let service2 = NamedNode::parse("http://service2.org").unwrap(); let service2 = NamedNode::parse("http://service2.org").unwrap();
if named_node == service1 { if named_node == &service1 {
Some(TwoServiceTest::handle_service1) Some(TwoServiceTest::handle_service1)
} else if named_node == service2 { } else if named_node == &service2 {
Some(TwoServiceTest::handle_service2) Some(TwoServiceTest::handle_service2)
} else { } else {
None None
@ -133,7 +133,7 @@ fn silent_service_empty_set_test() {
impl ServiceHandler for ServiceTest { impl ServiceHandler for ServiceTest {
fn handle<'a>( fn handle<'a>(
&'a self, &'a self,
_named_node: NamedNode, _named_node: &NamedNode,
) -> Option<(fn(GraphPattern) -> Result<BindingsIterator<'a>>)> { ) -> Option<(fn(GraphPattern) -> Result<BindingsIterator<'a>>)> {
Some(ServiceTest::handle_service) Some(ServiceTest::handle_service)
} }
@ -177,7 +177,7 @@ fn non_silent_service_test() {
impl ServiceHandler for ServiceTest { impl ServiceHandler for ServiceTest {
fn handle<'a>( fn handle<'a>(
&'a self, &'a self,
_named_node: NamedNode, _named_node: &NamedNode,
) -> Option<(fn(GraphPattern) -> Result<BindingsIterator<'a>>)> { ) -> Option<(fn(GraphPattern) -> Result<BindingsIterator<'a>>)> {
Some(ServiceTest::handle_service) Some(ServiceTest::handle_service)
} }
@ -242,10 +242,11 @@ fn query_repository<'a>(
query: String, query: String,
options: QueryOptions<'a>, options: QueryOptions<'a>,
) -> Result<BindingsIterator<'a>> { ) -> Result<BindingsIterator<'a>> {
let connection = repository.connection()?; match repository
let prepared_query = connection.prepare_query(&query, None)?; .connection()?
let result = prepared_query.exec(&options)?; .prepare_query(&query, options)?
match result { .exec()?
{
QueryResult::Bindings(iterator) => { QueryResult::Bindings(iterator) => {
let (varaibles, iter) = iterator.destruct(); let (varaibles, iter) = iterator.destruct();
let collected = iter.collect::<Vec<_>>(); let collected = iter.collect::<Vec<_>>();
@ -265,10 +266,11 @@ fn pattern_repository<'a>(
pattern: GraphPattern, pattern: GraphPattern,
options: QueryOptions<'a>, options: QueryOptions<'a>,
) -> Result<BindingsIterator<'a>> { ) -> Result<BindingsIterator<'a>> {
let connection = repository.connection()?; match repository
let prepared_query = connection.prepare_query_from_pattern(&pattern, None)?; .connection()?
let result = prepared_query.exec(&options)?; .prepare_query_from_pattern(&pattern, options)?
match result { .exec()?
{
QueryResult::Bindings(iterator) => { QueryResult::Bindings(iterator) => {
let (varaibles, iter) = iterator.destruct(); let (varaibles, iter) = iterator.destruct();
let collected = iter.collect::<Vec<_>>(); let collected = iter.collect::<Vec<_>>();
@ -277,9 +279,7 @@ fn pattern_repository<'a>(
Box::new(collected.into_iter()), Box::new(collected.into_iter()),
)) ))
} }
_ => Err(format_err!( _ => Err(format_err!("Expected bindings but got another QueryResult")),
"Excpected bindings but got another QueryResult"
)),
} }
} }

@ -158,13 +158,13 @@ fn sparql_w3c_query_evaluation_testsuite() -> Result<()> {
} }
match repository match repository
.connection()? .connection()?
.prepare_query(&read_file_to_string(&test.query)?, Some(&test.query)) .prepare_query(&read_file_to_string(&test.query)?, QueryOptions::default().with_base_iri(&test.query))
{ {
Err(error) => Err(format_err!( Err(error) => Err(format_err!(
"Failure to parse query of {} with error: {}", "Failure to parse query of {} with error: {}",
test, error test, error
)), )),
Ok(query) => match query.exec(&QueryOptions::default()) { Ok(query) => match query.exec() {
Err(error) => Err(format_err!( Err(error) => Err(format_err!(
"Failure to execute query of {} with error: {}", "Failure to execute query of {} with error: {}",
test, error test, error

@ -148,10 +148,9 @@ fn evaluate_sparql_query<R: RepositoryConnection>(
request: &Request, request: &Request,
) -> Response { ) -> Response {
//TODO: stream //TODO: stream
let options = QueryOptions::default(); match connection.prepare_query(query, QueryOptions::default()) {
match connection.prepare_query(query, None) {
Ok(query) => { Ok(query) => {
let results = query.exec(&options).unwrap(); let results = query.exec().unwrap();
if let QueryResult::Graph(_) = results { if let QueryResult::Graph(_) = results {
let supported_formats = [ let supported_formats = [
GraphSyntax::NTriples.media_type(), GraphSyntax::NTriples.media_type(),

Loading…
Cancel
Save