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

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

@ -4,10 +4,12 @@
use model::Dataset; use model::Dataset;
use sparql::algebra::Query; use sparql::algebra::Query;
use sparql::algebra::QueryResult; use sparql::algebra::QueryResult;
use sparql::algebra::Variable;
use sparql::eval::SimpleEvaluator; use sparql::eval::SimpleEvaluator;
use sparql::parser::read_sparql_query; use sparql::parser::read_sparql_query;
use sparql::plan::PlanBuilder;
use sparql::plan::PlanNode;
use std::io::Read; use std::io::Read;
use std::sync::Arc;
use store::encoded::EncodedQuadsStore; use store::encoded::EncodedQuadsStore;
use store::encoded::StoreDataset; use store::encoded::StoreDataset;
use Result; use Result;
@ -31,20 +33,37 @@ impl<S: EncodedQuadsStore> SparqlDataset for StoreDataset<S> {
type PreparedQuery = SimplePreparedQuery<S>; type PreparedQuery = SimplePreparedQuery<S>;
fn prepare_query(&self, query: impl Read) -> Result<SimplePreparedQuery<S>> { fn prepare_query(&self, query: impl Read) -> Result<SimplePreparedQuery<S>> {
Ok(SimplePreparedQuery { Ok(match read_sparql_query(query, None)? {
query: read_sparql_query(query, None)?, Query::Select { algebra, dataset } => {
store: self.encoded(), 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> { pub enum SimplePreparedQuery<S: EncodedQuadsStore> {
query: Query, Select {
store: Arc<S>, plan: PlanNode,
variables: Vec<Variable>,
evaluator: SimpleEvaluator<S>,
},
} }
impl<S: EncodedQuadsStore> PreparedQuery for SimplePreparedQuery<S> { impl<S: EncodedQuadsStore> PreparedQuery for SimplePreparedQuery<S> {
fn exec(&self) -> Result<QueryResult> { 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 std::str::FromStr;
use Result; 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 { enum State {
Start, Start,
Sparql, Sparql,

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

Loading…
Cancel
Save