From b0988aa4b95d4d3f2e4bbd1cef75ad160632f54b Mon Sep 17 00:00:00 2001 From: Tpt Date: Thu, 26 Sep 2019 12:26:05 +0200 Subject: [PATCH] Avoids to insert strings in the store while building the query plan --- lib/src/sparql/eval.rs | 64 +------------------------------- lib/src/sparql/mod.rs | 21 ++++++----- lib/src/sparql/plan.rs | 67 +++++++++++++++++++++++++++++++++- lib/src/sparql/plan_builder.rs | 39 +++++++++----------- 4 files changed, 96 insertions(+), 95 deletions(-) diff --git a/lib/src/sparql/eval.rs b/lib/src/sparql/eval.rs index 569cb361..01011f7c 100644 --- a/lib/src/sparql/eval.rs +++ b/lib/src/sparql/eval.rs @@ -3,7 +3,6 @@ use crate::model::Triple; use crate::sparql::model::*; use crate::sparql::plan::*; use crate::store::numeric_encoder::*; -use crate::store::numeric_encoder::{MemoryStringStore, ENCODED_EMPTY_STRING_LITERAL}; use crate::store::StoreConnection; use crate::Result; use chrono::prelude::*; @@ -47,9 +46,9 @@ pub struct SimpleEvaluator { } impl<'a, S: StoreConnection + 'a> SimpleEvaluator { - pub fn new(dataset: S, base_iri: Option>) -> Self { + pub fn new(dataset: DatasetView, base_iri: Option>) -> Self { Self { - dataset: DatasetView::new(dataset), + dataset, bnodes_map: Mutex::new(BTreeMap::default()), base_iri, now: Utc::now().with_timezone(&FixedOffset::east(0)), @@ -1822,65 +1821,6 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { } } -struct DatasetView { - store: S, - extra: MemoryStringStore, -} - -impl DatasetView { - fn new(store: S) -> Self { - Self { - store, - extra: MemoryStringStore::default(), - } - } - - fn quads_for_pattern<'a>( - &'a self, - subject: Option, - predicate: Option, - object: Option, - graph_name: Option, - ) -> Box> + 'a> { - self.store - .quads_for_pattern(subject, predicate, object, graph_name) - } - - fn encoder(&self) -> Encoder<&Self> { - Encoder::new(&self) - } -} - -impl StringStore for DatasetView { - type StringType = StringOrStoreString; - - fn get_str(&self, id: u64) -> Result>> { - Ok(if let Some(value) = self.store.get_str(id)? { - Some(StringOrStoreString::Store(value)) - } else if let Some(value) = self.extra.get_str(u64::MAX - id)? { - Some(StringOrStoreString::String(value)) - } else { - None - }) - } - - fn get_str_id(&self, value: &str) -> Result> { - Ok(if let Some(id) = self.store.get_str_id(value)? { - Some(id) - } else { - self.extra.get_str_id(value)?.map(|id| u64::MAX - id) - }) - } - - fn insert_str(&self, value: &str) -> Result { - Ok(if let Some(id) = self.store.get_str_id(value)? { - id - } else { - u64::MAX - self.extra.insert_str(value)? - }) - } -} - pub enum StringOrStoreString + ToString + Into> { String(String), Store(S), diff --git a/lib/src/sparql/mod.rs b/lib/src/sparql/mod.rs index 92249472..a48a4244 100644 --- a/lib/src/sparql/mod.rs +++ b/lib/src/sparql/mod.rs @@ -12,8 +12,8 @@ mod xml_results; use crate::sparql::algebra::QueryVariants; use crate::sparql::eval::SimpleEvaluator; use crate::sparql::parser::read_sparql_query; -use crate::sparql::plan::PlanNode; use crate::sparql::plan::TripleTemplate; +use crate::sparql::plan::{DatasetView, PlanNode}; use crate::sparql::plan_builder::PlanBuilder; use crate::store::StoreConnection; use crate::Result; @@ -56,6 +56,7 @@ enum SimplePreparedQueryOptions { impl SimplePreparedQuery { pub(crate) fn new(connection: S, query: &str, base_iri: Option<&str>) -> Result { + let dataset = DatasetView::new(connection); //TODO avoid inserting terms in the Repository StringStore Ok(Self(match read_sparql_query(query, base_iri)? { QueryVariants::Select { @@ -63,11 +64,11 @@ impl SimplePreparedQuery { dataset: _, base_iri, } => { - let (plan, variables) = PlanBuilder::build(&connection, &algebra)?; + let (plan, variables) = PlanBuilder::build(dataset.encoder(), &algebra)?; SimplePreparedQueryOptions::Select { plan, variables, - evaluator: SimpleEvaluator::new(connection, base_iri), + evaluator: SimpleEvaluator::new(dataset, base_iri), } } QueryVariants::Ask { @@ -75,10 +76,10 @@ impl SimplePreparedQuery { dataset: _, base_iri, } => { - let (plan, _) = PlanBuilder::build(&connection, &algebra)?; + let (plan, _) = PlanBuilder::build(dataset.encoder(), &algebra)?; SimplePreparedQueryOptions::Ask { plan, - evaluator: SimpleEvaluator::new(connection, base_iri), + evaluator: SimpleEvaluator::new(dataset, base_iri), } } QueryVariants::Construct { @@ -87,15 +88,15 @@ impl SimplePreparedQuery { dataset: _, base_iri, } => { - let (plan, variables) = PlanBuilder::build(&connection, &algebra)?; + let (plan, variables) = PlanBuilder::build(dataset.encoder(), &algebra)?; SimplePreparedQueryOptions::Construct { plan, construct: PlanBuilder::build_graph_template( - &connection, + dataset.encoder(), &construct, variables, )?, - evaluator: SimpleEvaluator::new(connection, base_iri), + evaluator: SimpleEvaluator::new(dataset, base_iri), } } QueryVariants::Describe { @@ -103,10 +104,10 @@ impl SimplePreparedQuery { dataset: _, base_iri, } => { - let (plan, _) = PlanBuilder::build(&connection, &algebra)?; + let (plan, _) = PlanBuilder::build(dataset.encoder(), &algebra)?; SimplePreparedQueryOptions::Describe { plan, - evaluator: SimpleEvaluator::new(connection, base_iri), + evaluator: SimpleEvaluator::new(dataset, base_iri), } } })) diff --git a/lib/src/sparql/plan.rs b/lib/src/sparql/plan.rs index 41641b90..a8bdde19 100644 --- a/lib/src/sparql/plan.rs +++ b/lib/src/sparql/plan.rs @@ -1,5 +1,11 @@ -use crate::store::numeric_encoder::EncodedTerm; +use crate::sparql::eval::StringOrStoreString; +use crate::store::numeric_encoder::{ + EncodedQuad, EncodedTerm, Encoder, MemoryStringStore, StringStore, +}; +use crate::store::StoreConnection; +use crate::Result; use std::collections::BTreeSet; +use std::u64; pub type EncodedTuple = Vec>; @@ -452,3 +458,62 @@ pub enum TripleTemplateValue { BlankNode(usize), Variable(usize), } + +pub struct DatasetView { + store: S, + extra: MemoryStringStore, +} + +impl DatasetView { + pub fn new(store: S) -> Self { + Self { + store, + extra: MemoryStringStore::default(), + } + } + + pub fn quads_for_pattern<'a>( + &'a self, + subject: Option, + predicate: Option, + object: Option, + graph_name: Option, + ) -> Box> + 'a> { + self.store + .quads_for_pattern(subject, predicate, object, graph_name) + } + + pub fn encoder(&self) -> Encoder<&Self> { + Encoder::new(&self) + } +} + +impl StringStore for DatasetView { + type StringType = StringOrStoreString; + + fn get_str(&self, id: u64) -> Result>> { + Ok(if let Some(value) = self.store.get_str(id)? { + Some(StringOrStoreString::Store(value)) + } else if let Some(value) = self.extra.get_str(u64::MAX - id)? { + Some(StringOrStoreString::String(value)) + } else { + None + }) + } + + fn get_str_id(&self, value: &str) -> Result> { + Ok(if let Some(id) = self.store.get_str_id(value)? { + Some(id) + } else { + self.extra.get_str_id(value)?.map(|id| u64::MAX - id) + }) + } + + fn insert_str(&self, value: &str) -> Result { + Ok(if let Some(id) = self.store.get_str_id(value)? { + id + } else { + u64::MAX - self.extra.insert_str(value)? + }) + } +} diff --git a/lib/src/sparql/plan_builder.rs b/lib/src/sparql/plan_builder.rs index 7b1b72d5..095d87ea 100644 --- a/lib/src/sparql/plan_builder.rs +++ b/lib/src/sparql/plan_builder.rs @@ -4,20 +4,19 @@ use crate::sparql::algebra::*; use crate::sparql::model::*; use crate::sparql::plan::PlanPropertyPath; use crate::sparql::plan::*; -use crate::store::numeric_encoder::ENCODED_DEFAULT_GRAPH; -use crate::store::StoreConnection; +use crate::store::numeric_encoder::{Encoder, StringStore, ENCODED_DEFAULT_GRAPH}; use crate::Result; use failure::format_err; use std::collections::HashSet; -pub struct PlanBuilder<'a, S: StoreConnection> { - store: &'a S, +pub struct PlanBuilder { + encoder: Encoder, } -impl<'a, S: StoreConnection> PlanBuilder<'a, S> { - pub fn build(store: &'a S, pattern: &GraphPattern) -> Result<(PlanNode, Vec)> { +impl PlanBuilder { + pub fn build(encoder: Encoder, pattern: &GraphPattern) -> Result<(PlanNode, Vec)> { let mut variables = Vec::default(); - let plan = PlanBuilder { store }.build_for_graph_pattern( + let plan = PlanBuilder { encoder }.build_for_graph_pattern( pattern, &mut variables, PatternValue::Constant(ENCODED_DEFAULT_GRAPH), @@ -26,11 +25,11 @@ impl<'a, S: StoreConnection> PlanBuilder<'a, S> { } pub fn build_graph_template( - store: &S, + encoder: Encoder, template: &[TriplePattern], mut variables: Vec, ) -> Result> { - PlanBuilder { store }.build_for_graph_template(template, &mut variables) + PlanBuilder { encoder }.build_for_graph_template(template, &mut variables) } fn build_for_graph_pattern( @@ -231,7 +230,7 @@ impl<'a, S: StoreConnection> PlanBuilder<'a, S> { fn build_for_path(&self, path: &PropertyPath) -> Result { Ok(match path { PropertyPath::PredicatePath(p) => { - PlanPropertyPath::PredicatePath(self.store.encoder().encode_named_node(p)?) + PlanPropertyPath::PredicatePath(self.encoder.encode_named_node(p)?) } PropertyPath::InversePath(p) => { PlanPropertyPath::InversePath(Box::new(self.build_for_path(p)?)) @@ -255,7 +254,7 @@ impl<'a, S: StoreConnection> PlanBuilder<'a, S> { } PropertyPath::NegatedPropertySet(p) => PlanPropertyPath::NegatedPropertySet( p.iter() - .map(|p| self.store.encoder().encode_named_node(p)) + .map(|p| self.encoder.encode_named_node(p)) .collect::>>()?, ), }) @@ -269,9 +268,7 @@ impl<'a, S: StoreConnection> PlanBuilder<'a, S> { ) -> Result { Ok(match expression { Expression::Constant(t) => match t { - TermOrVariable::Term(t) => { - PlanExpression::Constant(self.store.encoder().encode_term(t)?) - } + TermOrVariable::Term(t) => PlanExpression::Constant(self.encoder.encode_term(t)?), TermOrVariable::Variable(v) => PlanExpression::Variable(variable_key(variables, v)), }, Expression::Or(a, b) => PlanExpression::Or( @@ -691,9 +688,7 @@ impl<'a, S: StoreConnection> PlanBuilder<'a, S> { variables: &mut Vec, ) -> Result { Ok(match term_or_variable { - TermOrVariable::Term(term) => { - PatternValue::Constant(self.store.encoder().encode_term(term)?) - } + TermOrVariable::Term(term) => PatternValue::Constant(self.encoder.encode_term(term)?), TermOrVariable::Variable(variable) => { PatternValue::Variable(variable_key(variables, variable)) } @@ -707,7 +702,7 @@ impl<'a, S: StoreConnection> PlanBuilder<'a, S> { ) -> Result { Ok(match named_node_or_variable { NamedNodeOrVariable::NamedNode(named_node) => { - PatternValue::Constant(self.store.encoder().encode_named_node(named_node)?) + PatternValue::Constant(self.encoder.encode_named_node(named_node)?) } NamedNodeOrVariable::Variable(variable) => { PatternValue::Variable(variable_key(variables, variable)) @@ -720,7 +715,6 @@ impl<'a, S: StoreConnection> PlanBuilder<'a, S> { bindings: &StaticBindings, variables: &mut Vec, ) -> Result> { - let encoder = self.store.encoder(); let bindings_variables_keys = bindings .variables() .iter() @@ -732,7 +726,8 @@ impl<'a, S: StoreConnection> PlanBuilder<'a, S> { let mut result = vec![None; variables.len()]; for (key, value) in values.iter().enumerate() { if let Some(term) = value { - result[bindings_variables_keys[key]] = Some(encoder.encode_term(term)?); + result[bindings_variables_keys[key]] = + Some(self.encoder.encode_term(term)?); } } Ok(result) @@ -828,7 +823,7 @@ impl<'a, S: StoreConnection> PlanBuilder<'a, S> { ) -> Result { Ok(match term_or_variable { TermOrVariable::Term(term) => { - TripleTemplateValue::Constant(self.store.encoder().encode_term(term)?) + TripleTemplateValue::Constant(self.encoder.encode_term(term)?) } TermOrVariable::Variable(variable) => { if variable.has_name() { @@ -848,7 +843,7 @@ impl<'a, S: StoreConnection> PlanBuilder<'a, S> { ) -> Result { Ok(match named_node_or_variable { NamedNodeOrVariable::NamedNode(term) => { - TripleTemplateValue::Constant(self.store.encoder().encode_named_node(term)?) + TripleTemplateValue::Constant(self.encoder.encode_named_node(term)?) } NamedNodeOrVariable::Variable(variable) => { if variable.has_name() {