Allows to set BindingsIterator lifetime

Will allow to avoid a lot of copies
pull/10/head
Tpt 6 years ago
parent 1772f3df07
commit bd5c737334
  1. 18
      lib/src/sparql/algebra.rs
  2. 56
      lib/src/sparql/eval.rs
  3. 35
      lib/src/sparql/mod.rs
  4. 2
      lib/src/sparql/xml_results.rs
  5. 42
      lib/tests/sparql_test_cases.rs

@ -167,7 +167,7 @@ impl StaticBindings {
self.values.iter()
}
pub fn into_iterator(self) -> BindingsIterator {
pub fn into_iterator(self) -> BindingsIterator<'static> {
BindingsIterator {
variables: self.variables,
iter: Box::new(self.values.into_iter().map(Ok)),
@ -188,15 +188,15 @@ impl Default for StaticBindings {
}
}
pub struct BindingsIterator {
pub struct BindingsIterator<'a> {
variables: Vec<Variable>,
iter: Box<dyn Iterator<Item = Result<Vec<Option<Term>>>>>,
iter: Box<dyn Iterator<Item = Result<Vec<Option<Term>>>> + 'a>,
}
impl BindingsIterator {
impl<'a> BindingsIterator<'a> {
pub fn new(
variables: Vec<Variable>,
iter: Box<dyn Iterator<Item = Result<Vec<Option<Term>>>>>,
iter: Box<dyn Iterator<Item = Result<Vec<Option<Term>>>> + 'a>,
) -> Self {
Self { variables, iter }
}
@ -205,7 +205,7 @@ impl BindingsIterator {
&*self.variables
}
pub fn into_values_iter(self) -> Box<dyn Iterator<Item = Result<Vec<Option<Term>>>>> {
pub fn into_values_iter(self) -> Box<dyn Iterator<Item = Result<Vec<Option<Term>>>> + 'a> {
self.iter
}
@ -213,7 +213,7 @@ impl BindingsIterator {
self,
) -> (
Vec<Variable>,
Box<dyn Iterator<Item = Result<Vec<Option<Term>>>>>,
Box<dyn Iterator<Item = Result<Vec<Option<Term>>>> + 'a>,
) {
(self.variables, self.iter)
}
@ -1574,8 +1574,8 @@ impl fmt::Display for Query {
}
}
pub enum QueryResult {
Bindings(BindingsIterator),
pub enum QueryResult<'a> {
Bindings(BindingsIterator<'a>),
Boolean(bool),
Graph(MemoryGraph),
}

@ -21,7 +21,7 @@ use store::encoded::EncodedQuadsStore;
use store::numeric_encoder::*;
use Result;
type EncodedTuplesIterator = Box<dyn Iterator<Item = Result<EncodedTuple>>>;
type EncodedTuplesIterator<'a> = Box<dyn Iterator<Item = Result<EncodedTuple>> + 'a>;
pub struct SimpleEvaluator<S: EncodedQuadsStore> {
store: Arc<S>,
@ -40,18 +40,18 @@ impl<S: EncodedQuadsStore> SimpleEvaluator<S> {
Self { store }
}
pub fn evaluate(&self, query: &Query) -> Result<QueryResult> {
match query {
Query::Select { algebra, dataset } => {
let (plan, variables) = PlanBuilder::build(&*self.store, algebra)?;
let iter = self.eval_plan(plan, vec![None; variables.len()]);
Ok(QueryResult::Bindings(self.decode_bindings(iter, variables)))
}
_ => unimplemented!(),
}
pub fn evaluate_select_plan<'a>(
&'a self,
plan: &PlanNode,
variables: &[Variable],
) -> Result<QueryResult<'a>> {
let iter = self.eval_plan(plan.clone(), vec![None; variables.len()]);
Ok(QueryResult::Bindings(
self.decode_bindings(iter, variables.to_vec()),
))
}
fn eval_plan(&self, node: PlanNode, from: EncodedTuple) -> EncodedTuplesIterator {
fn eval_plan<'a>(&self, node: PlanNode, from: EncodedTuple) -> EncodedTuplesIterator<'a> {
match node {
PlanNode::Init => Box::new(once(Ok(from))),
PlanNode::StaticBindings { tuples } => Box::new(tuples.into_iter().map(Ok)),
@ -648,11 +648,11 @@ impl<S: EncodedQuadsStore> SimpleEvaluator<S> {
}
}
fn decode_bindings(
fn decode_bindings<'a>(
&self,
iter: EncodedTuplesIterator,
iter: EncodedTuplesIterator<'a>,
variables: Vec<Variable>,
) -> BindingsIterator {
) -> BindingsIterator<'a> {
let store = self.store.clone();
BindingsIterator::new(
variables,
@ -807,13 +807,13 @@ fn combine_tuples(a: &[Option<EncodedTerm>], b: &[Option<EncodedTerm>]) -> Optio
}
}
struct JoinIterator {
struct JoinIterator<'a> {
left: Vec<EncodedTuple>,
right_iter: EncodedTuplesIterator,
right_iter: EncodedTuplesIterator<'a>,
buffered_results: Vec<Result<EncodedTuple>>,
}
impl Iterator for JoinIterator {
impl<'a> Iterator for JoinIterator<'a> {
type Item = Result<EncodedTuple>;
fn next(&mut self) -> Option<Result<EncodedTuple>> {
@ -833,14 +833,14 @@ impl Iterator for JoinIterator {
}
}
struct LeftJoinIterator<S: EncodedQuadsStore> {
struct LeftJoinIterator<'a, S: EncodedQuadsStore> {
eval: SimpleEvaluator<S>,
right_plan: PlanNode,
left_iter: EncodedTuplesIterator,
current_right_iter: Option<EncodedTuplesIterator>,
left_iter: EncodedTuplesIterator<'a>,
current_right_iter: Option<EncodedTuplesIterator<'a>>,
}
impl<S: EncodedQuadsStore> Iterator for LeftJoinIterator<S> {
impl<'a, S: EncodedQuadsStore> Iterator for LeftJoinIterator<'a, S> {
type Item = Result<EncodedTuple>;
fn next(&mut self) -> Option<Result<EncodedTuple>> {
@ -867,13 +867,13 @@ impl<S: EncodedQuadsStore> Iterator for LeftJoinIterator<S> {
}
}
struct BadLeftJoinIterator<S: EncodedQuadsStore> {
struct BadLeftJoinIterator<'a, S: EncodedQuadsStore> {
input: EncodedTuple,
iter: LeftJoinIterator<S>,
iter: LeftJoinIterator<'a, S>,
problem_vars: Vec<usize>,
}
impl<S: EncodedQuadsStore> Iterator for BadLeftJoinIterator<S> {
impl<'a, S: EncodedQuadsStore> Iterator for BadLeftJoinIterator<'a, S> {
type Item = Result<EncodedTuple>;
fn next(&mut self) -> Option<Result<EncodedTuple>> {
@ -903,14 +903,14 @@ impl<S: EncodedQuadsStore> Iterator for BadLeftJoinIterator<S> {
}
}
struct UnionIterator<S: EncodedQuadsStore> {
struct UnionIterator<'a, S: EncodedQuadsStore> {
eval: SimpleEvaluator<S>,
children_plan: Vec<PlanNode>,
input_iter: EncodedTuplesIterator,
current_iters: Vec<EncodedTuplesIterator>,
input_iter: EncodedTuplesIterator<'a>,
current_iters: Vec<EncodedTuplesIterator<'a>>,
}
impl<S: EncodedQuadsStore> Iterator for UnionIterator<S> {
impl<'a, S: EncodedQuadsStore> Iterator for UnionIterator<'a, S> {
type Item = Result<EncodedTuple>;
fn next(&mut self) -> Option<Result<EncodedTuple>> {

@ -4,10 +4,12 @@
use model::Dataset;
use sparql::algebra::Query;
use sparql::algebra::QueryResult;
use sparql::algebra::Variable;
use sparql::eval::SimpleEvaluator;
use sparql::parser::read_sparql_query;
use sparql::plan::PlanBuilder;
use sparql::plan::PlanNode;
use std::io::Read;
use std::sync::Arc;
use store::encoded::EncodedQuadsStore;
use store::encoded::StoreDataset;
use Result;
@ -31,20 +33,37 @@ impl<S: EncodedQuadsStore> SparqlDataset for StoreDataset<S> {
type PreparedQuery = SimplePreparedQuery<S>;
fn prepare_query(&self, query: impl Read) -> Result<SimplePreparedQuery<S>> {
Ok(SimplePreparedQuery {
query: read_sparql_query(query, None)?,
store: self.encoded(),
Ok(match read_sparql_query(query, None)? {
Query::Select { algebra, dataset } => {
let store = self.encoded();
let (plan, variables) = PlanBuilder::build(&*store, &algebra)?;
SimplePreparedQuery::Select {
plan,
variables,
evaluator: SimpleEvaluator::new(store),
}
}
_ => unimplemented!(),
})
}
}
pub struct SimplePreparedQuery<S: EncodedQuadsStore> {
query: Query,
store: Arc<S>,
pub enum SimplePreparedQuery<S: EncodedQuadsStore> {
Select {
plan: PlanNode,
variables: Vec<Variable>,
evaluator: SimpleEvaluator<S>,
},
}
impl<S: EncodedQuadsStore> PreparedQuery for SimplePreparedQuery<S> {
fn exec(&self) -> Result<QueryResult> {
SimpleEvaluator::new(self.store.clone()).evaluate(&self.query)
match self {
SimplePreparedQuery::Select {
plan,
variables,
evaluator,
} => evaluator.evaluate_select_plan(&plan, &variables),
}
}
}

@ -10,7 +10,7 @@ use std::iter::empty;
use std::str::FromStr;
use Result;
pub fn read_xml_results(source: impl BufRead + 'static) -> Result<QueryResult> {
pub fn read_xml_results(source: impl BufRead + 'static) -> Result<QueryResult<'static>> {
enum State {
Start,
Sparql,

@ -211,30 +211,34 @@ fn sparql_w3c_query_evaluation_testsuite() {
.unwrap()
.for_each(|triple| named_graph.insert(&triple.unwrap()).unwrap());
}
match data
.prepare_query(client.get(&test.query).unwrap())
.and_then(|p| p.exec())
{
match data.prepare_query(client.get(&test.query).unwrap()) {
Err(error) => assert!(
false,
"Failure to parse query of {} with error: {}",
test, error
),
Ok(result) => {
let actual_graph = to_graph(result).unwrap();
let expected_graph = client
.load_sparql_query_result_graph(test.result.clone().unwrap())
.unwrap();
assert!(
actual_graph.is_isomorphic(&expected_graph).unwrap(),
"Failure on {}.\nExpected file:\n{}\nOutput file:\n{}\nParsed query:\n{}\nData:\n{}\n",
test,
expected_graph,
actual_graph,
client.load_sparql_query(test.query.clone()).unwrap(),
data
)
}
Ok(query) => match query.exec() {
Err(error) => assert!(
false,
"Failure to execute query of {} with error: {}",
test, error
),
Ok(result) => {
let actual_graph = to_graph(result).unwrap();
let expected_graph = client
.load_sparql_query_result_graph(test.result.clone().unwrap())
.unwrap();
assert!(
actual_graph.is_isomorphic(&expected_graph).unwrap(),
"Failure on {}.\nExpected file:\n{}\nOutput file:\n{}\nParsed query:\n{}\nData:\n{}\n",
test,
expected_graph,
actual_graph,
client.load_sparql_query(test.query.clone()).unwrap(),
data
)
}
},
}
} else {
assert!(false, "Not supported test: {}", test);

Loading…
Cancel
Save