Rework SPARQL algebra and makes it public

pull/71/head
Tpt 4 years ago
parent 40a08ac623
commit 34f0efbb39
  1. 1516
      lib/src/sparql/algebra.rs
  2. 172
      lib/src/sparql/eval.rs
  3. 69
      lib/src/sparql/mod.rs
  4. 473
      lib/src/sparql/parser.rs
  5. 44
      lib/src/sparql/plan.rs
  6. 347
      lib/src/sparql/plan_builder.rs
  7. 4
      lib/src/sparql/update.rs
  8. 2
      lib/src/store/memory.rs
  9. 2
      lib/src/store/rocksdb.rs
  10. 2
      lib/src/store/sled.rs

File diff suppressed because it is too large Load Diff

@ -2,7 +2,7 @@ use crate::model::vocab::{rdf, xsd};
use crate::model::xsd::*; use crate::model::xsd::*;
use crate::model::Triple; use crate::model::Triple;
use crate::model::{BlankNode, LiteralRef, NamedNodeRef}; use crate::model::{BlankNode, LiteralRef, NamedNodeRef};
use crate::sparql::algebra::{GraphPattern, Query, QueryDataset, QueryVariants}; use crate::sparql::algebra::{GraphPattern, Query, QueryDataset};
use crate::sparql::error::EvaluationError; use crate::sparql::error::EvaluationError;
use crate::sparql::model::*; use crate::sparql::model::*;
use crate::sparql::plan::*; use crate::sparql::plan::*;
@ -134,25 +134,22 @@ where
service_name, service_name,
graph_pattern, graph_pattern,
.. ..
} => match self.evaluate_service( } => {
service_name, match self.evaluate_service(service_name, graph_pattern, variables.clone(), &from) {
graph_pattern.clone(), Ok(result) => Box::new(result.flat_map(move |binding| {
variables.clone(), binding
&from, .map(|binding| binding.combine_with(&from))
) { .transpose()
Ok(result) => Box::new(result.flat_map(move |binding| { })),
binding Err(e) => {
.map(|binding| binding.combine_with(&from)) if *silent {
.transpose() Box::new(once(Ok(from)))
})), } else {
Err(e) => { Box::new(once(Err(e)))
if *silent { }
Box::new(once(Ok(from)))
} else {
Box::new(once(Err(e)))
} }
} }
}, }
PlanNode::QuadPatternJoin { PlanNode::QuadPatternJoin {
child, child,
subject, subject,
@ -516,7 +513,7 @@ where
fn evaluate_service( fn evaluate_service(
&self, &self,
service_name: &PatternValue<S::StrId>, service_name: &PatternValue<S::StrId>,
graph_pattern: Rc<GraphPattern>, graph_pattern: &GraphPattern,
variables: Rc<Vec<Variable>>, variables: Rc<Vec<Variable>>,
from: &EncodedTuple<S::StrId>, from: &EncodedTuple<S::StrId>,
) -> Result<EncodedTuplesIterator<S::StrId>, EvaluationError> { ) -> Result<EncodedTuplesIterator<S::StrId>, EvaluationError> {
@ -525,11 +522,11 @@ where
get_pattern_value(service_name, from) get_pattern_value(service_name, from)
.ok_or_else(|| EvaluationError::msg("The SERVICE name is not bound"))?, .ok_or_else(|| EvaluationError::msg("The SERVICE name is not bound"))?,
)?, )?,
Query(QueryVariants::Select { Query::Select {
dataset: QueryDataset::default(), dataset: QueryDataset::default(),
algebra: graph_pattern, pattern: graph_pattern.clone(),
base_iri: self.base_iri.clone(), base_iri: self.base_iri.as_ref().map(|iri| iri.as_ref().clone()),
}), },
)? { )? {
Ok(self.encode_bindings(variables, iter)) Ok(self.encode_bindings(variables, iter))
} else { } else {
@ -589,13 +586,13 @@ where
graph_name: EncodedTerm<S::StrId>, graph_name: EncodedTerm<S::StrId>,
) -> Box<dyn Iterator<Item = Result<EncodedTerm<S::StrId>, EvaluationError>>> { ) -> Box<dyn Iterator<Item = Result<EncodedTerm<S::StrId>, EvaluationError>>> {
match path { match path {
PlanPropertyPath::PredicatePath(p) => Box::new( PlanPropertyPath::Path(p) => Box::new(
self.dataset self.dataset
.encoded_quads_for_pattern(Some(start), Some(*p), None, Some(graph_name)) .encoded_quads_for_pattern(Some(start), Some(*p), None, Some(graph_name))
.map(|t| Ok(t?.object)), .map(|t| Ok(t?.object)),
), ),
PlanPropertyPath::InversePath(p) => self.eval_path_to(p, start, graph_name), PlanPropertyPath::Reverse(p) => self.eval_path_to(p, start, graph_name),
PlanPropertyPath::SequencePath(a, b) => { PlanPropertyPath::Sequence(a, b) => {
let eval = self.clone(); let eval = self.clone();
let b = b.clone(); let b = b.clone();
Box::new( Box::new(
@ -603,18 +600,18 @@ where
.flat_map_ok(move |middle| eval.eval_path_from(&b, middle, graph_name)), .flat_map_ok(move |middle| eval.eval_path_from(&b, middle, graph_name)),
) )
} }
PlanPropertyPath::AlternativePath(a, b) => Box::new( PlanPropertyPath::Alternative(a, b) => Box::new(
self.eval_path_from(a, start, graph_name) self.eval_path_from(a, start, graph_name)
.chain(self.eval_path_from(b, start, graph_name)), .chain(self.eval_path_from(b, start, graph_name)),
), ),
PlanPropertyPath::ZeroOrMorePath(p) => { PlanPropertyPath::ZeroOrMore(p) => {
let eval = self.clone(); let eval = self.clone();
let p = p.clone(); let p = p.clone();
Box::new(transitive_closure(Some(Ok(start)), move |e| { Box::new(transitive_closure(Some(Ok(start)), move |e| {
eval.eval_path_from(&p, e, graph_name) eval.eval_path_from(&p, e, graph_name)
})) }))
} }
PlanPropertyPath::OneOrMorePath(p) => { PlanPropertyPath::OneOrMore(p) => {
let eval = self.clone(); let eval = self.clone();
let p = p.clone(); let p = p.clone();
Box::new(transitive_closure( Box::new(transitive_closure(
@ -622,7 +619,7 @@ where
move |e| eval.eval_path_from(&p, e, graph_name), move |e| eval.eval_path_from(&p, e, graph_name),
)) ))
} }
PlanPropertyPath::ZeroOrOnePath(p) => Box::new(hash_deduplicate( PlanPropertyPath::ZeroOrOne(p) => Box::new(hash_deduplicate(
once(Ok(start)).chain(self.eval_path_from(p, start, graph_name)), once(Ok(start)).chain(self.eval_path_from(p, start, graph_name)),
)), )),
PlanPropertyPath::NegatedPropertySet(ps) => { PlanPropertyPath::NegatedPropertySet(ps) => {
@ -652,13 +649,13 @@ where
graph_name: EncodedTerm<S::StrId>, graph_name: EncodedTerm<S::StrId>,
) -> Box<dyn Iterator<Item = Result<EncodedTerm<S::StrId>, EvaluationError>>> { ) -> Box<dyn Iterator<Item = Result<EncodedTerm<S::StrId>, EvaluationError>>> {
match path { match path {
PlanPropertyPath::PredicatePath(p) => Box::new( PlanPropertyPath::Path(p) => Box::new(
self.dataset self.dataset
.encoded_quads_for_pattern(None, Some(*p), Some(end), Some(graph_name)) .encoded_quads_for_pattern(None, Some(*p), Some(end), Some(graph_name))
.map(|t| Ok(t?.subject)), .map(|t| Ok(t?.subject)),
), ),
PlanPropertyPath::InversePath(p) => self.eval_path_from(p, end, graph_name), PlanPropertyPath::Reverse(p) => self.eval_path_from(p, end, graph_name),
PlanPropertyPath::SequencePath(a, b) => { PlanPropertyPath::Sequence(a, b) => {
let eval = self.clone(); let eval = self.clone();
let a = a.clone(); let a = a.clone();
Box::new( Box::new(
@ -666,18 +663,18 @@ where
.flat_map_ok(move |middle| eval.eval_path_to(&a, middle, graph_name)), .flat_map_ok(move |middle| eval.eval_path_to(&a, middle, graph_name)),
) )
} }
PlanPropertyPath::AlternativePath(a, b) => Box::new( PlanPropertyPath::Alternative(a, b) => Box::new(
self.eval_path_to(a, end, graph_name) self.eval_path_to(a, end, graph_name)
.chain(self.eval_path_to(b, end, graph_name)), .chain(self.eval_path_to(b, end, graph_name)),
), ),
PlanPropertyPath::ZeroOrMorePath(p) => { PlanPropertyPath::ZeroOrMore(p) => {
let eval = self.clone(); let eval = self.clone();
let p = p.clone(); let p = p.clone();
Box::new(transitive_closure(Some(Ok(end)), move |e| { Box::new(transitive_closure(Some(Ok(end)), move |e| {
eval.eval_path_to(&p, e, graph_name) eval.eval_path_to(&p, e, graph_name)
})) }))
} }
PlanPropertyPath::OneOrMorePath(p) => { PlanPropertyPath::OneOrMore(p) => {
let eval = self.clone(); let eval = self.clone();
let p = p.clone(); let p = p.clone();
Box::new(transitive_closure( Box::new(transitive_closure(
@ -685,7 +682,7 @@ where
move |e| eval.eval_path_to(&p, e, graph_name), move |e| eval.eval_path_to(&p, e, graph_name),
)) ))
} }
PlanPropertyPath::ZeroOrOnePath(p) => Box::new(hash_deduplicate( PlanPropertyPath::ZeroOrOne(p) => Box::new(hash_deduplicate(
once(Ok(end)).chain(self.eval_path_to(p, end, graph_name)), once(Ok(end)).chain(self.eval_path_to(p, end, graph_name)),
)), )),
PlanPropertyPath::NegatedPropertySet(ps) => { PlanPropertyPath::NegatedPropertySet(ps) => {
@ -718,16 +715,16 @@ where
>, >,
> { > {
match path { match path {
PlanPropertyPath::PredicatePath(p) => Box::new( PlanPropertyPath::Path(p) => Box::new(
self.dataset self.dataset
.encoded_quads_for_pattern(None, Some(*p), None, Some(graph_name)) .encoded_quads_for_pattern(None, Some(*p), None, Some(graph_name))
.map(|t| t.map(|t| (t.subject, t.object))), .map(|t| t.map(|t| (t.subject, t.object))),
), ),
PlanPropertyPath::InversePath(p) => Box::new( PlanPropertyPath::Reverse(p) => Box::new(
self.eval_open_path(p, graph_name) self.eval_open_path(p, graph_name)
.map(|t| t.map(|(s, o)| (o, s))), .map(|t| t.map(|(s, o)| (o, s))),
), ),
PlanPropertyPath::SequencePath(a, b) => { PlanPropertyPath::Sequence(a, b) => {
let eval = self.clone(); let eval = self.clone();
let b = b.clone(); let b = b.clone();
Box::new( Box::new(
@ -738,11 +735,11 @@ where
}), }),
) )
} }
PlanPropertyPath::AlternativePath(a, b) => Box::new( PlanPropertyPath::Alternative(a, b) => Box::new(
self.eval_open_path(a, graph_name) self.eval_open_path(a, graph_name)
.chain(self.eval_open_path(b, graph_name)), .chain(self.eval_open_path(b, graph_name)),
), ),
PlanPropertyPath::ZeroOrMorePath(p) => { PlanPropertyPath::ZeroOrMore(p) => {
let eval = self.clone(); let eval = self.clone();
let p = p.clone(); let p = p.clone();
Box::new(transitive_closure( Box::new(transitive_closure(
@ -753,7 +750,7 @@ where
}, },
)) ))
} }
PlanPropertyPath::OneOrMorePath(p) => { PlanPropertyPath::OneOrMore(p) => {
let eval = self.clone(); let eval = self.clone();
let p = p.clone(); let p = p.clone();
Box::new(transitive_closure( Box::new(transitive_closure(
@ -764,7 +761,7 @@ where
}, },
)) ))
} }
PlanPropertyPath::ZeroOrOnePath(p) => Box::new(hash_deduplicate( PlanPropertyPath::ZeroOrOne(p) => Box::new(hash_deduplicate(
self.get_subject_or_object_identity_pairs(graph_name) self.get_subject_or_object_identity_pairs(graph_name)
.chain(self.eval_open_path(p, graph_name)), .chain(self.eval_open_path(p, graph_name)),
)), )),
@ -845,11 +842,6 @@ where
let b = self.eval_expression(b, tuple)?; let b = self.eval_expression(b, tuple)?;
self.equals(a, b).map(|v| v.into()) self.equals(a, b).map(|v| v.into())
} }
PlanExpression::NotEqual(a, b) => {
let a = self.eval_expression(a, tuple)?;
let b = self.eval_expression(b, tuple)?;
self.equals(a, b).map(|v| (!v).into())
}
PlanExpression::Greater(a, b) => Some( PlanExpression::Greater(a, b) => Some(
(self.partial_cmp_literals( (self.partial_cmp_literals(
self.eval_expression(a, tuple)?, self.eval_expression(a, tuple)?,
@ -857,7 +849,7 @@ where
)? == Ordering::Greater) )? == Ordering::Greater)
.into(), .into(),
), ),
PlanExpression::GreaterOrEq(a, b) => Some( PlanExpression::GreaterOrEqual(a, b) => Some(
match self.partial_cmp_literals( match self.partial_cmp_literals(
self.eval_expression(a, tuple)?, self.eval_expression(a, tuple)?,
self.eval_expression(b, tuple)?, self.eval_expression(b, tuple)?,
@ -867,14 +859,14 @@ where
} }
.into(), .into(),
), ),
PlanExpression::Lower(a, b) => Some( PlanExpression::Less(a, b) => Some(
(self.partial_cmp_literals( (self.partial_cmp_literals(
self.eval_expression(a, tuple)?, self.eval_expression(a, tuple)?,
self.eval_expression(b, tuple)?, self.eval_expression(b, tuple)?,
)? == Ordering::Less) )? == Ordering::Less)
.into(), .into(),
), ),
PlanExpression::LowerOrEq(a, b) => Some( PlanExpression::LessOrEqual(a, b) => Some(
match self.partial_cmp_literals( match self.partial_cmp_literals(
self.eval_expression(a, tuple)?, self.eval_expression(a, tuple)?,
self.eval_expression(b, tuple)?, self.eval_expression(b, tuple)?,
@ -938,46 +930,52 @@ where
} }
_ => None, _ => None,
}, },
PlanExpression::Sub(a, b) => Some(match self.parse_numeric_operands(a, b, tuple)? { PlanExpression::Subtract(a, b) => {
NumericBinaryOperands::Float(v1, v2) => (v1 - v2).into(), Some(match self.parse_numeric_operands(a, b, tuple)? {
NumericBinaryOperands::Double(v1, v2) => (v1 - v2).into(), NumericBinaryOperands::Float(v1, v2) => (v1 - v2).into(),
NumericBinaryOperands::Integer(v1, v2) => v1.checked_sub(v2)?.into(), NumericBinaryOperands::Double(v1, v2) => (v1 - v2).into(),
NumericBinaryOperands::Decimal(v1, v2) => v1.checked_sub(v2)?.into(), NumericBinaryOperands::Integer(v1, v2) => v1.checked_sub(v2)?.into(),
NumericBinaryOperands::DateTime(v1, v2) => v1.checked_sub(v2)?.into(), NumericBinaryOperands::Decimal(v1, v2) => v1.checked_sub(v2)?.into(),
NumericBinaryOperands::Date(v1, v2) => v1.checked_sub(v2)?.into(), NumericBinaryOperands::DateTime(v1, v2) => v1.checked_sub(v2)?.into(),
NumericBinaryOperands::Time(v1, v2) => v1.checked_sub(v2)?.into(), NumericBinaryOperands::Date(v1, v2) => v1.checked_sub(v2)?.into(),
NumericBinaryOperands::Duration(v1, v2) => v1.checked_sub(v2)?.into(), NumericBinaryOperands::Time(v1, v2) => v1.checked_sub(v2)?.into(),
NumericBinaryOperands::YearMonthDuration(v1, v2) => v1.checked_sub(v2)?.into(), NumericBinaryOperands::Duration(v1, v2) => v1.checked_sub(v2)?.into(),
NumericBinaryOperands::DayTimeDuration(v1, v2) => v1.checked_sub(v2)?.into(), NumericBinaryOperands::YearMonthDuration(v1, v2) => v1.checked_sub(v2)?.into(),
NumericBinaryOperands::DateTimeDuration(v1, v2) => { NumericBinaryOperands::DayTimeDuration(v1, v2) => v1.checked_sub(v2)?.into(),
v1.checked_sub_duration(v2)?.into() NumericBinaryOperands::DateTimeDuration(v1, v2) => {
} v1.checked_sub_duration(v2)?.into()
NumericBinaryOperands::DateTimeYearMonthDuration(v1, v2) => { }
v1.checked_sub_year_month_duration(v2)?.into() NumericBinaryOperands::DateTimeYearMonthDuration(v1, v2) => {
} v1.checked_sub_year_month_duration(v2)?.into()
NumericBinaryOperands::DateTimeDayTimeDuration(v1, v2) => { }
v1.checked_sub_day_time_duration(v2)?.into() NumericBinaryOperands::DateTimeDayTimeDuration(v1, v2) => {
} v1.checked_sub_day_time_duration(v2)?.into()
NumericBinaryOperands::DateDuration(v1, v2) => v1.checked_sub_duration(v2)?.into(), }
NumericBinaryOperands::DateYearMonthDuration(v1, v2) => { NumericBinaryOperands::DateDuration(v1, v2) => {
v1.checked_sub_year_month_duration(v2)?.into() v1.checked_sub_duration(v2)?.into()
} }
NumericBinaryOperands::DateDayTimeDuration(v1, v2) => { NumericBinaryOperands::DateYearMonthDuration(v1, v2) => {
v1.checked_sub_day_time_duration(v2)?.into() v1.checked_sub_year_month_duration(v2)?.into()
} }
NumericBinaryOperands::TimeDuration(v1, v2) => v1.checked_sub_duration(v2)?.into(), NumericBinaryOperands::DateDayTimeDuration(v1, v2) => {
NumericBinaryOperands::TimeDayTimeDuration(v1, v2) => { v1.checked_sub_day_time_duration(v2)?.into()
v1.checked_sub_day_time_duration(v2)?.into() }
} NumericBinaryOperands::TimeDuration(v1, v2) => {
}), v1.checked_sub_duration(v2)?.into()
PlanExpression::Mul(a, b) => match self.parse_numeric_operands(a, b, tuple)? { }
NumericBinaryOperands::TimeDayTimeDuration(v1, v2) => {
v1.checked_sub_day_time_duration(v2)?.into()
}
})
}
PlanExpression::Multiply(a, b) => match self.parse_numeric_operands(a, b, tuple)? {
NumericBinaryOperands::Float(v1, v2) => Some((v1 * v2).into()), NumericBinaryOperands::Float(v1, v2) => Some((v1 * v2).into()),
NumericBinaryOperands::Double(v1, v2) => Some((v1 * v2).into()), NumericBinaryOperands::Double(v1, v2) => Some((v1 * v2).into()),
NumericBinaryOperands::Integer(v1, v2) => Some(v1.checked_mul(v2)?.into()), NumericBinaryOperands::Integer(v1, v2) => Some(v1.checked_mul(v2)?.into()),
NumericBinaryOperands::Decimal(v1, v2) => Some(v1.checked_mul(v2)?.into()), NumericBinaryOperands::Decimal(v1, v2) => Some(v1.checked_mul(v2)?.into()),
_ => None, _ => None,
}, },
PlanExpression::Div(a, b) => match self.parse_numeric_operands(a, b, tuple)? { PlanExpression::Divide(a, b) => match self.parse_numeric_operands(a, b, tuple)? {
NumericBinaryOperands::Float(v1, v2) => Some((v1 / v2).into()), NumericBinaryOperands::Float(v1, v2) => Some((v1 / v2).into()),
NumericBinaryOperands::Double(v1, v2) => Some((v1 / v2).into()), NumericBinaryOperands::Double(v1, v2) => Some((v1 / v2).into()),
NumericBinaryOperands::Integer(v1, v2) => { NumericBinaryOperands::Integer(v1, v2) => {
@ -1006,7 +1004,7 @@ where
EncodedTerm::DayTimeDurationLiteral(value) => Some((-value).into()), EncodedTerm::DayTimeDurationLiteral(value) => Some((-value).into()),
_ => None, _ => None,
}, },
PlanExpression::UnaryNot(e) => self PlanExpression::Not(e) => self
.to_bool(self.eval_expression(e, tuple)?) .to_bool(self.eval_expression(e, tuple)?)
.map(|v| (!v).into()), .map(|v| (!v).into()),
PlanExpression::Str(e) => { PlanExpression::Str(e) => {

@ -2,7 +2,7 @@
//! //!
//! Stores execute SPARQL. See [`MemoryStore`](super::store::memory::MemoryStore::query()) for an example. //! Stores execute SPARQL. See [`MemoryStore`](super::store::memory::MemoryStore::query()) for an example.
mod algebra; pub mod algebra;
mod csv_results; mod csv_results;
mod dataset; mod dataset;
mod error; mod error;
@ -17,7 +17,6 @@ mod service;
mod update; mod update;
mod xml_results; mod xml_results;
use crate::sparql::algebra::QueryVariants;
pub use crate::sparql::algebra::{Query, Update}; pub use crate::sparql::algebra::{Query, Update};
use crate::sparql::dataset::DatasetView; use crate::sparql::dataset::DatasetView;
pub use crate::sparql::error::EvaluationError; pub use crate::sparql::error::EvaluationError;
@ -44,48 +43,64 @@ pub(crate) fn evaluate_query<R: ReadableEncodedStore + 'static>(
query: impl TryInto<Query, Error = impl Into<EvaluationError>>, query: impl TryInto<Query, Error = impl Into<EvaluationError>>,
options: QueryOptions, options: QueryOptions,
) -> Result<QueryResults, EvaluationError> { ) -> Result<QueryResults, EvaluationError> {
match query.try_into().map_err(|e| e.into())?.0 { match query.try_into().map_err(|e| e.into())? {
QueryVariants::Select { Query::Select {
algebra, pattern,
base_iri, base_iri,
dataset, dataset,
} => { } => {
let dataset = DatasetView::new(store, &dataset)?; let dataset = DatasetView::new(store, &dataset)?;
let (plan, variables) = PlanBuilder::build(&dataset, &algebra)?; let (plan, variables) = PlanBuilder::build(&dataset, &pattern)?;
SimpleEvaluator::new(Rc::new(dataset), base_iri, options.service_handler) SimpleEvaluator::new(
.evaluate_select_plan(&plan, Rc::new(variables)) Rc::new(dataset),
base_iri.map(Rc::new),
options.service_handler,
)
.evaluate_select_plan(&plan, Rc::new(variables))
} }
QueryVariants::Ask { Query::Ask {
algebra, pattern,
base_iri, base_iri,
dataset, dataset,
} => { } => {
let dataset = DatasetView::new(store, &dataset)?; let dataset = DatasetView::new(store, &dataset)?;
let (plan, _) = PlanBuilder::build(&dataset, &algebra)?; let (plan, _) = PlanBuilder::build(&dataset, &pattern)?;
SimpleEvaluator::new(Rc::new(dataset), base_iri, options.service_handler) SimpleEvaluator::new(
.evaluate_ask_plan(&plan) Rc::new(dataset),
base_iri.map(Rc::new),
options.service_handler,
)
.evaluate_ask_plan(&plan)
} }
QueryVariants::Construct { Query::Construct {
construct, template,
algebra, pattern,
base_iri, base_iri,
dataset, dataset,
} => { } => {
let dataset = DatasetView::new(store, &dataset)?; let dataset = DatasetView::new(store, &dataset)?;
let (plan, variables) = PlanBuilder::build(&dataset, &algebra)?; let (plan, variables) = PlanBuilder::build(&dataset, &pattern)?;
let construct = PlanBuilder::build_graph_template(&dataset, &construct, variables)?; let construct = PlanBuilder::build_graph_template(&dataset, &template, variables)?;
SimpleEvaluator::new(Rc::new(dataset), base_iri, options.service_handler) SimpleEvaluator::new(
.evaluate_construct_plan(&plan, construct) Rc::new(dataset),
base_iri.map(Rc::new),
options.service_handler,
)
.evaluate_construct_plan(&plan, construct)
} }
QueryVariants::Describe { Query::Describe {
algebra, pattern,
base_iri, base_iri,
dataset, dataset,
} => { } => {
let dataset = DatasetView::new(store, &dataset)?; let dataset = DatasetView::new(store, &dataset)?;
let (plan, _) = PlanBuilder::build(&dataset, &algebra)?; let (plan, _) = PlanBuilder::build(&dataset, &pattern)?;
SimpleEvaluator::new(Rc::new(dataset), base_iri, options.service_handler) SimpleEvaluator::new(
.evaluate_describe_plan(&plan) Rc::new(dataset),
base_iri.map(Rc::new),
options.service_handler,
)
.evaluate_describe_plan(&plan)
} }
} }
} }
@ -135,7 +150,7 @@ pub(crate) fn evaluate_update<
>( >(
read: R, read: R,
write: &mut W, write: &mut W,
update: &Update, update: Update,
) -> Result<(), EvaluationError> ) -> Result<(), EvaluationError>
where where
io::Error: From<StoreOrParseError<W::Error>>, io::Error: From<StoreOrParseError<W::Error>>,
@ -143,7 +158,7 @@ where
SimpleUpdateEvaluator::new( SimpleUpdateEvaluator::new(
read, read,
write, write,
update.base_iri.clone(), update.base_iri.map(Rc::new),
Rc::new(EmptyServiceHandler), Rc::new(EmptyServiceHandler),
) )
.eval_all(&update.operations) .eval_all(&update.operations)

@ -18,45 +18,41 @@ use std::{char, fmt};
pub fn parse_query(query: &str, base_iri: Option<&str>) -> Result<Query, ParseError> { pub fn parse_query(query: &str, base_iri: Option<&str>) -> Result<Query, ParseError> {
let mut state = ParserState { let mut state = ParserState {
base_iri: if let Some(base_iri) = base_iri { base_iri: if let Some(base_iri) = base_iri {
Some(Rc::new(Iri::parse(base_iri.to_owned()).map_err(|e| { Some(Iri::parse(base_iri.to_owned()).map_err(|e| ParseError {
ParseError { inner: ParseErrorKind::InvalidBaseIri(e),
inner: ParseErrorKind::InvalidBaseIri(e), })?)
}
})?))
} else { } else {
None None
}, },
namespaces: HashMap::default(), namespaces: HashMap::default(),
used_bnodes: HashSet::default(), used_bnodes: HashSet::default(),
currently_used_bnodes: HashSet::default(), currently_used_bnodes: HashSet::default(),
aggregations: Vec::default(), aggregates: Vec::default(),
}; };
Ok(Query( Ok(
parser::QueryUnit(&unescape_unicode_codepoints(query), &mut state).map_err(|e| { parser::QueryUnit(&unescape_unicode_codepoints(query), &mut state).map_err(|e| {
ParseError { ParseError {
inner: ParseErrorKind::Parser(e), inner: ParseErrorKind::Parser(e),
} }
})?, })?,
)) )
} }
/// Parses a SPARQL update with an optional base IRI to resolve relative IRIs in the query /// Parses a SPARQL update with an optional base IRI to resolve relative IRIs in the query
pub fn parse_update(update: &str, base_iri: Option<&str>) -> Result<Update, ParseError> { pub fn parse_update(update: &str, base_iri: Option<&str>) -> Result<Update, ParseError> {
let mut state = ParserState { let mut state = ParserState {
base_iri: if let Some(base_iri) = base_iri { base_iri: if let Some(base_iri) = base_iri {
Some(Rc::new(Iri::parse(base_iri.to_owned()).map_err(|e| { Some(Iri::parse(base_iri.to_owned()).map_err(|e| ParseError {
ParseError { inner: ParseErrorKind::InvalidBaseIri(e),
inner: ParseErrorKind::InvalidBaseIri(e), })?)
}
})?))
} else { } else {
None None
}, },
namespaces: HashMap::default(), namespaces: HashMap::default(),
used_bnodes: HashSet::default(), used_bnodes: HashSet::default(),
currently_used_bnodes: HashSet::default(), currently_used_bnodes: HashSet::default(),
aggregations: Vec::default(), aggregates: Vec::default(),
}; };
let operations = let operations =
@ -131,7 +127,7 @@ impl<F> From<FocusedTriplePattern<F>> for FocusedTriplePattern<Vec<F>> {
#[derive(Clone)] #[derive(Clone)]
enum VariableOrPropertyPath { enum VariableOrPropertyPath {
Variable(Variable), Variable(Variable),
PropertyPath(PropertyPath), PropertyPath(PropertyPathExpression),
} }
impl From<Variable> for VariableOrPropertyPath { impl From<Variable> for VariableOrPropertyPath {
@ -140,8 +136,8 @@ impl From<Variable> for VariableOrPropertyPath {
} }
} }
impl From<PropertyPath> for VariableOrPropertyPath { impl From<PropertyPathExpression> for VariableOrPropertyPath {
fn from(path: PropertyPath) -> Self { fn from(path: PropertyPathExpression) -> Self {
VariableOrPropertyPath::PropertyPath(path) VariableOrPropertyPath::PropertyPath(path)
} }
} }
@ -157,22 +153,68 @@ fn add_to_triple_or_path_patterns(
patterns.push(TriplePattern::new(subject, p, object).into()) patterns.push(TriplePattern::new(subject, p, object).into())
} }
VariableOrPropertyPath::PropertyPath(p) => match p { VariableOrPropertyPath::PropertyPath(p) => match p {
PropertyPath::PredicatePath(p) => { PropertyPathExpression::NamedNode(p) => {
patterns.push(TriplePattern::new(subject, p, object).into()) patterns.push(TriplePattern::new(subject, p, object).into())
} }
PropertyPath::InversePath(p) => { PropertyPathExpression::Reverse(p) => {
add_to_triple_or_path_patterns(object, *p, subject, patterns) add_to_triple_or_path_patterns(object, *p, subject, patterns)
} }
PropertyPath::SequencePath(a, b) => { PropertyPathExpression::Sequence(a, b) => {
let middle = BlankNode::default(); let middle = BlankNode::default();
add_to_triple_or_path_patterns(subject, *a, middle.clone().into(), patterns); add_to_triple_or_path_patterns(subject, *a, middle.clone().into(), patterns);
add_to_triple_or_path_patterns(middle.into(), *b, object, patterns); add_to_triple_or_path_patterns(middle.into(), *b, object, patterns);
} }
p => patterns.push(PathPattern::new(subject, p, object).into()), path => patterns.push(TripleOrPathPattern::Path {
subject,
path,
object,
}),
}, },
} }
} }
fn build_bgp(patterns: Vec<TripleOrPathPattern>) -> GraphPattern {
let mut bgp = Vec::with_capacity(patterns.len());
let mut paths = Vec::with_capacity(patterns.len());
for pattern in patterns {
match pattern {
TripleOrPathPattern::Triple(t) => bgp.push(t),
TripleOrPathPattern::Path {
subject,
path,
object,
} => paths.push((subject, path, object)),
}
}
let mut graph_pattern = GraphPattern::BGP(bgp);
for (subject, path, object) in paths {
graph_pattern = new_join(
graph_pattern,
GraphPattern::Path {
subject,
path,
object,
},
)
}
graph_pattern
}
enum TripleOrPathPattern {
Triple(TriplePattern),
Path {
subject: TermOrVariable,
path: PropertyPathExpression,
object: TermOrVariable,
},
}
impl From<TriplePattern> for TripleOrPathPattern {
fn from(tp: TriplePattern) -> Self {
TripleOrPathPattern::Triple(tp)
}
}
struct FocusedTripleOrPathPattern<F> { struct FocusedTripleOrPathPattern<F> {
focus: F, focus: F,
patterns: Vec<TripleOrPathPattern>, patterns: Vec<TripleOrPathPattern>,
@ -239,14 +281,29 @@ fn new_join(l: GraphPattern, r: GraphPattern) -> GraphPattern {
//Merge BGPs //Merge BGPs
match (l, r) { match (l, r) {
(GraphPattern::BGP(mut pl), GraphPattern::BGP(pr)) => { (GraphPattern::BGP(mut pl), GraphPattern::BGP(pr)) => {
pl.extend_from_slice(&pr); pl.extend(pr);
GraphPattern::BGP(pl) GraphPattern::BGP(pl)
} }
(GraphPattern::Graph(g1, l), GraphPattern::Graph(g2, r)) if g1 == g2 => { (
GraphPattern::Graph {
graph_name: g1,
inner: l,
},
GraphPattern::Graph {
graph_name: g2,
inner: r,
},
) if g1 == g2 => {
// We merge identical graphs // We merge identical graphs
GraphPattern::Graph(g1, Box::new(new_join(*l, *r))) GraphPattern::Graph {
graph_name: g1,
inner: Box::new(new_join(*l, *r)),
}
} }
(l, r) => GraphPattern::Join(Box::new(l), Box::new(r)), (l, r) => GraphPattern::Join {
left: Box::new(l),
right: Box::new(r),
},
} }
} }
@ -299,8 +356,8 @@ fn build_select(
let mut p = wher; let mut p = wher;
//GROUP BY //GROUP BY
let aggregations = state.aggregations.pop().unwrap_or_else(Vec::default); let aggregates = state.aggregates.pop().unwrap_or_else(Vec::default);
if group.is_none() && !aggregations.is_empty() { if group.is_none() && !aggregates.is_empty() {
let const_variable = Variable::new_random(); let const_variable = Variable::new_random();
group = Some(( group = Some((
vec![const_variable.clone()], vec![const_variable.clone()],
@ -309,16 +366,26 @@ fn build_select(
} }
if let Some((clauses, binds)) = group { if let Some((clauses, binds)) = group {
for (e, v) in binds { for (expr, var) in binds {
p = GraphPattern::Extend(Box::new(p), v, e); p = GraphPattern::Extend {
} inner: Box::new(p),
let g = GroupPattern(clauses, Box::new(p)); var,
p = GraphPattern::AggregateJoin(g, aggregations); expr,
};
}
p = GraphPattern::Group {
inner: Box::new(p),
by: clauses,
aggregates,
};
} }
//HAVING //HAVING
if let Some(ex) = having { if let Some(expr) = having {
p = GraphPattern::Filter(ex, Box::new(p)); p = GraphPattern::Filter {
expr,
inner: Box::new(p),
};
} }
//VALUES //VALUES
@ -333,11 +400,15 @@ fn build_select(
for sel_item in sel_items { for sel_item in sel_items {
match sel_item { match sel_item {
SelectionMember::Variable(v) => pv.push(v), SelectionMember::Variable(v) => pv.push(v),
SelectionMember::Expression(e, v) => { SelectionMember::Expression(expr, v) => {
if pv.contains(&v) { if pv.contains(&v) {
//TODO: fail //TODO: fail
} else { } else {
p = GraphPattern::Extend(Box::new(p), v.clone(), e); p = GraphPattern::Extend {
inner: Box::new(p),
var: v.clone(),
expr,
};
pv.push(v); pv.push(v);
} }
} }
@ -351,50 +422,58 @@ fn build_select(
let mut m = p; let mut m = p;
//ORDER BY //ORDER BY
if let Some(order) = order_by { if let Some(condition) = order_by {
m = GraphPattern::OrderBy(Box::new(m), order); m = GraphPattern::OrderBy {
inner: Box::new(m),
condition,
};
} }
//PROJECT //PROJECT
m = GraphPattern::Project(Box::new(m), pv); m = GraphPattern::Project {
inner: Box::new(m),
projection: pv,
};
match select.option { match select.option {
SelectionOption::Distinct => m = GraphPattern::Distinct(Box::new(m)), SelectionOption::Distinct => m = GraphPattern::Distinct { inner: Box::new(m) },
SelectionOption::Reduced => m = GraphPattern::Reduced(Box::new(m)), SelectionOption::Reduced => m = GraphPattern::Reduced { inner: Box::new(m) },
SelectionOption::Default => (), SelectionOption::Default => (),
} }
//OFFSET LIMIT //OFFSET LIMIT
if let Some((offset, limit)) = offset_limit { if let Some((start, length)) = offset_limit {
m = GraphPattern::Slice(Box::new(m), offset, limit) m = GraphPattern::Slice {
inner: Box::new(m),
start,
length,
}
} }
m m
} }
fn copy_graph( fn copy_graph(from: Option<NamedNode>, to: Option<NamedNodeOrVariable>) -> GraphUpdateOperation {
from: NamedOrDefaultGraphTarget,
to: impl Into<Option<NamedNodeOrVariable>>,
) -> GraphUpdateOperation {
let bgp = GraphPattern::BGP(vec![TriplePattern::new( let bgp = GraphPattern::BGP(vec![TriplePattern::new(
Variable::new_unchecked("s"), Variable::new_unchecked("s"),
Variable::new_unchecked("p"), Variable::new_unchecked("p"),
Variable::new_unchecked("o"), Variable::new_unchecked("o"),
) )]);
.into()]);
GraphUpdateOperation::DeleteInsert { GraphUpdateOperation::DeleteInsert {
delete: Vec::new(), delete: Vec::new(),
insert: vec![QuadPattern::new( insert: vec![QuadPattern::new(
Variable::new_unchecked("s"), Variable::new_unchecked("s"),
Variable::new_unchecked("p"), Variable::new_unchecked("p"),
Variable::new_unchecked("o"), Variable::new_unchecked("o"),
to.into(), to,
)], )],
using: QueryDataset::default(), using: QueryDataset::default(),
algebra: match from { pattern: Box::new(if let Some(from) = from {
NamedOrDefaultGraphTarget::NamedNode(from) => { GraphPattern::Graph {
GraphPattern::Graph(from.into(), Box::new(bgp)) graph_name: from.into(),
inner: Box::new(bgp),
} }
NamedOrDefaultGraphTarget::DefaultGraph => bgp, } else {
}, bgp
}),
} }
} }
@ -404,11 +483,11 @@ enum Either<L, R> {
} }
pub struct ParserState { pub struct ParserState {
base_iri: Option<Rc<Iri<String>>>, base_iri: Option<Iri<String>>,
namespaces: HashMap<String, String>, namespaces: HashMap<String, String>,
used_bnodes: HashSet<BlankNode>, used_bnodes: HashSet<BlankNode>,
currently_used_bnodes: HashSet<BlankNode>, currently_used_bnodes: HashSet<BlankNode>,
aggregations: Vec<Vec<(Aggregation, Variable)>>, aggregates: Vec<Vec<(Variable, SetFunction)>>,
} }
impl ParserState { impl ParserState {
@ -420,15 +499,15 @@ impl ParserState {
} }
} }
fn new_aggregation(&mut self, agg: Aggregation) -> Result<Variable, &'static str> { fn new_aggregation(&mut self, agg: SetFunction) -> Result<Variable, &'static str> {
let aggregations = self.aggregations.last_mut().ok_or("Unexpected aggregate")?; let aggregates = self.aggregates.last_mut().ok_or("Unexpected aggregate")?;
Ok(aggregations Ok(aggregates
.iter() .iter()
.find_map(|(a, v)| if a == &agg { Some(v) } else { None }) .find_map(|(v, a)| if a == &agg { Some(v) } else { None })
.cloned() .cloned()
.unwrap_or_else(|| { .unwrap_or_else(|| {
let new_var = Variable::new_random(); let new_var = Variable::new_random();
aggregations.push((agg, new_var.clone())); aggregates.push((new_var.clone(), agg));
new_var new_var
})) }))
} }
@ -642,10 +721,10 @@ parser! {
//See https://www.w3.org/TR/turtle/#sec-grammar //See https://www.w3.org/TR/turtle/#sec-grammar
grammar parser(state: &mut ParserState) for str { grammar parser(state: &mut ParserState) for str {
//[1] //[1]
pub rule QueryUnit() -> QueryVariants = Query() pub rule QueryUnit() -> Query = Query()
//[2] //[2]
rule Query() -> QueryVariants = _ Prologue() _ q:(SelectQuery() / ConstructQuery() / DescribeQuery() / AskQuery()) _ { rule Query() -> Query = _ Prologue() _ q:(SelectQuery() / ConstructQuery() / DescribeQuery() / AskQuery()) _ {
q q
} }
@ -657,7 +736,7 @@ parser! {
//[5] //[5]
rule BaseDecl() = i("BASE") _ i:IRIREF() { rule BaseDecl() = i("BASE") _ i:IRIREF() {
state.base_iri = Some(Rc::new(i)) state.base_iri = Some(i)
} }
//[6] //[6]
@ -666,10 +745,10 @@ parser! {
} }
//[7] //[7]
rule SelectQuery() -> QueryVariants = s:SelectClause() _ d:DatasetClauses() _ w:WhereClause() _ g:GroupClause()? _ h:HavingClause()? _ o:OrderClause()? _ l:LimitOffsetClauses()? _ v:ValuesClause() { rule SelectQuery() -> Query = s:SelectClause() _ d:DatasetClauses() _ w:WhereClause() _ g:GroupClause()? _ h:HavingClause()? _ o:OrderClause()? _ l:LimitOffsetClauses()? _ v:ValuesClause() {
QueryVariants::Select { Query::Select {
dataset: d, dataset: d,
algebra: Rc::new(build_select(s, w, g, h, o, l, v, state)), pattern: build_select(s, w, g, h, o, l, v, state),
base_iri: state.base_iri.clone() base_iri: state.base_iri.clone()
} }
} }
@ -687,7 +766,7 @@ parser! {
} }
} }
rule Selection_init() = { rule Selection_init() = {
state.aggregations.push(Vec::default()) state.aggregates.push(Vec::default())
} }
rule SelectClause_option() -> SelectionOption = rule SelectClause_option() -> SelectionOption =
i("DISTINCT") { SelectionOption::Distinct } / i("DISTINCT") { SelectionOption::Distinct } /
@ -701,24 +780,24 @@ parser! {
"(" _ e:Expression() _ i("AS") _ v:Var() _ ")" _ { SelectionMember::Expression(e, v) } "(" _ e:Expression() _ i("AS") _ v:Var() _ ")" _ { SelectionMember::Expression(e, v) }
//[10] //[10]
rule ConstructQuery() -> QueryVariants = rule ConstructQuery() -> Query =
i("CONSTRUCT") _ c:ConstructTemplate() _ d:DatasetClauses() _ w:WhereClause() _ g:GroupClause()? _ h:HavingClause()? _ o:OrderClause()? _ l:LimitOffsetClauses()? _ v:ValuesClause() { i("CONSTRUCT") _ c:ConstructTemplate() _ d:DatasetClauses() _ w:WhereClause() _ g:GroupClause()? _ h:HavingClause()? _ o:OrderClause()? _ l:LimitOffsetClauses()? _ v:ValuesClause() {
QueryVariants::Construct { Query::Construct {
construct: Rc::new(c), template: c,
dataset: d, dataset: d,
algebra: Rc::new(build_select(Selection::default(), w, g, h, o, l, v, state)), pattern: build_select(Selection::default(), w, g, h, o, l, v, state),
base_iri: state.base_iri.clone() base_iri: state.base_iri.clone()
} }
} / } /
i("CONSTRUCT") _ d:DatasetClauses() _ i("WHERE") _ "{" _ c:ConstructQuery_optional_triple_template() _ "}" _ g:GroupClause()? _ h:HavingClause()? _ o:OrderClause()? _ l:LimitOffsetClauses()? _ v:ValuesClause() { i("CONSTRUCT") _ d:DatasetClauses() _ i("WHERE") _ "{" _ c:ConstructQuery_optional_triple_template() _ "}" _ g:GroupClause()? _ h:HavingClause()? _ o:OrderClause()? _ l:LimitOffsetClauses()? _ v:ValuesClause() {
QueryVariants::Construct { Query::Construct {
construct: Rc::new(c.clone()), template: c.clone(),
dataset: d, dataset: d,
algebra: Rc::new(build_select( pattern: build_select(
Selection::default(), Selection::default(),
GraphPattern::BGP(c.into_iter().map(TripleOrPathPattern::from).collect()), GraphPattern::BGP(c),
g, h, o, l, v, state g, h, o, l, v, state
)), ),
base_iri: state.base_iri.clone() base_iri: state.base_iri.clone()
} }
} }
@ -726,34 +805,34 @@ parser! {
rule ConstructQuery_optional_triple_template() -> Vec<TriplePattern> = TriplesTemplate() / { Vec::default() } rule ConstructQuery_optional_triple_template() -> Vec<TriplePattern> = TriplesTemplate() / { Vec::default() }
//[11] //[11]
rule DescribeQuery() -> QueryVariants = rule DescribeQuery() -> Query =
i("DESCRIBE") _ "*" _ d:DatasetClauses() w:WhereClause()? _ g:GroupClause()? _ h:HavingClause()? _ o:OrderClause()? _ l:LimitOffsetClauses()? _ v:ValuesClause() { i("DESCRIBE") _ "*" _ d:DatasetClauses() w:WhereClause()? _ g:GroupClause()? _ h:HavingClause()? _ o:OrderClause()? _ l:LimitOffsetClauses()? _ v:ValuesClause() {
QueryVariants::Describe { Query::Describe {
dataset: d, dataset: d,
algebra: Rc::new(build_select(Selection::default(), w.unwrap_or_else(GraphPattern::default), g, h, o, l, v, state)), pattern: build_select(Selection::default(), w.unwrap_or_else(GraphPattern::default), g, h, o, l, v, state),
base_iri: state.base_iri.clone() base_iri: state.base_iri.clone()
} }
} / } /
i("DESCRIBE") _ p:DescribeQuery_item()+ _ d:DatasetClauses() w:WhereClause()? _ g:GroupClause()? _ h:HavingClause()? _ o:OrderClause()? _ l:LimitOffsetClauses()? _ v:ValuesClause() { i("DESCRIBE") _ p:DescribeQuery_item()+ _ d:DatasetClauses() w:WhereClause()? _ g:GroupClause()? _ h:HavingClause()? _ o:OrderClause()? _ l:LimitOffsetClauses()? _ v:ValuesClause() {
QueryVariants::Describe { Query::Describe {
dataset: d, dataset: d,
algebra: Rc::new(build_select(Selection { pattern: build_select(Selection {
option: SelectionOption::Default, option: SelectionOption::Default,
variables: Some(p.into_iter().map(|var_or_iri| match var_or_iri { variables: Some(p.into_iter().map(|var_or_iri| match var_or_iri {
NamedNodeOrVariable::NamedNode(n) => SelectionMember::Expression(n.into(), Variable::new_random()), NamedNodeOrVariable::NamedNode(n) => SelectionMember::Expression(n.into(), Variable::new_random()),
NamedNodeOrVariable::Variable(v) => SelectionMember::Variable(v) NamedNodeOrVariable::Variable(v) => SelectionMember::Variable(v)
}).collect()) }).collect())
}, w.unwrap_or_else(GraphPattern::default), g, h, o, l, v, state)), }, w.unwrap_or_else(GraphPattern::default), g, h, o, l, v, state),
base_iri: state.base_iri.clone() base_iri: state.base_iri.clone()
} }
} }
rule DescribeQuery_item() -> NamedNodeOrVariable = i:VarOrIri() _ { i } rule DescribeQuery_item() -> NamedNodeOrVariable = i:VarOrIri() _ { i }
//[12] //[12]
rule AskQuery() -> QueryVariants = i("ASK") _ d:DatasetClauses() w:WhereClause() _ g:GroupClause()? _ h:HavingClause()? _ o:OrderClause()? _ l:LimitOffsetClauses()? _ v:ValuesClause() { rule AskQuery() -> Query = i("ASK") _ d:DatasetClauses() w:WhereClause() _ g:GroupClause()? _ h:HavingClause()? _ o:OrderClause()? _ l:LimitOffsetClauses()? _ v:ValuesClause() {
QueryVariants::Ask { Query::Ask {
dataset: d, dataset: d,
algebra: Rc::new(build_select(Selection::default(), w, g, h, o, l, v, state)), pattern: Rc::new(build_select(Selection::default(), w, g, h, o, l, v, state)),
base_iri: state.base_iri.clone() base_iri: state.base_iri.clone()
} }
} }
@ -837,8 +916,8 @@ parser! {
rule OrderCondition() -> OrderComparator = rule OrderCondition() -> OrderComparator =
i("ASC") _ e: BrackettedExpression() { OrderComparator::Asc(e) } / i("ASC") _ e: BrackettedExpression() { OrderComparator::Asc(e) } /
i("DESC") _ e: BrackettedExpression() { OrderComparator::Desc(e) } / i("DESC") _ e: BrackettedExpression() { OrderComparator::Desc(e) } /
e: Constraint() { e.into() } / e: Constraint() { OrderComparator::Asc(e) } /
v: Var() { Expression::from(v).into() } v: Var() { OrderComparator::Asc(Expression::from(v)) }
//[25] //[25]
rule LimitOffsetClauses() -> (usize, Option<usize>) = rule LimitOffsetClauses() -> (usize, Option<usize>) =
@ -895,8 +974,8 @@ parser! {
if from == to { if from == to {
Vec::new() // identity case Vec::new() // identity case
} else { } else {
let bgp = GraphPattern::BGP(vec![TriplePattern::new(Variable::new_unchecked("s"), Variable::new_unchecked("p"), Variable::new_unchecked("o")).into()]); let bgp = GraphPattern::BGP(vec![TriplePattern::new(Variable::new_unchecked("s"), Variable::new_unchecked("p"), Variable::new_unchecked("o"))]);
vec![copy_graph(from, to)] vec![copy_graph(from, to.map(NamedNodeOrVariable::NamedNode))]
} }
} }
@ -906,8 +985,8 @@ parser! {
if from == to { if from == to {
Vec::new() // identity case Vec::new() // identity case
} else { } else {
let bgp = GraphPattern::BGP(vec![TriplePattern::new(Variable::new_unchecked("s"), Variable::new_unchecked("p"), Variable::new_unchecked("o")).into()]); let bgp = GraphPattern::BGP(vec![TriplePattern::new(Variable::new_unchecked("s"), Variable::new_unchecked("p"), Variable::new_unchecked("o"))]);
vec![GraphUpdateOperation::Drop { silent, graph: to.clone().into() }, copy_graph(from.clone(), to), GraphUpdateOperation::Drop { silent, graph: from.into() }] vec![GraphUpdateOperation::Drop { silent, graph: to.clone().map_or(GraphTarget::DefaultGraph, GraphTarget::NamedNode) }, copy_graph(from.clone(), to.map(NamedNodeOrVariable::NamedNode)), GraphUpdateOperation::Drop { silent, graph: from.map_or(GraphTarget::DefaultGraph, GraphTarget::NamedNode) }]
} }
} }
@ -917,8 +996,8 @@ parser! {
if from == to { if from == to {
Vec::new() // identity case Vec::new() // identity case
} else { } else {
let bgp = GraphPattern::BGP(vec![TriplePattern::new(Variable::new_unchecked("s"), Variable::new_unchecked("p"), Variable::new_unchecked("o")).into()]); let bgp = GraphPattern::BGP(vec![TriplePattern::new(Variable::new_unchecked("s"), Variable::new_unchecked("p"), Variable::new_unchecked("o"))]);
vec![GraphUpdateOperation::Drop { silent, graph: to.clone().into() }, copy_graph(from, to)] vec![GraphUpdateOperation::Drop { silent, graph: to.clone().map_or(GraphTarget::DefaultGraph, GraphTarget::NamedNode) }, copy_graph(from, to.map(NamedNodeOrVariable::NamedNode))]
} }
} }
@ -934,10 +1013,10 @@ parser! {
//[40] //[40]
rule DeleteWhere() -> Vec<GraphUpdateOperation> = i("DELETE") _ i("WHERE") _ d:QuadData() { rule DeleteWhere() -> Vec<GraphUpdateOperation> = i("DELETE") _ i("WHERE") _ d:QuadData() {
let algebra = d.iter().map(|q| { let pattern = d.iter().map(|q| {
let bgp = GraphPattern::BGP(vec![TriplePattern::new(q.subject.clone(), q.predicate.clone(), q.object.clone()).into()]); let bgp = GraphPattern::BGP(vec![TriplePattern::new(q.subject.clone(), q.predicate.clone(), q.object.clone())]);
if let Some(graph_name) = &q.graph_name { if let Some(graph_name) = &q.graph_name {
GraphPattern::Graph(graph_name.clone(), Box::new(bgp)) GraphPattern::Graph { graph_name: graph_name.clone(), inner: Box::new(bgp) }
} else { } else {
bgp bgp
} }
@ -946,16 +1025,16 @@ parser! {
delete: d, delete: d,
insert: Vec::new(), insert: Vec::new(),
using: QueryDataset::default(), using: QueryDataset::default(),
algebra pattern: Box::new(pattern)
}] }]
} }
//[41] //[41]
rule Modify() -> Vec<GraphUpdateOperation> = with:Modify_with()? _ Modify_clear() c:Modify_clauses() _ u:(UsingClause() ** (_)) _ i("WHERE") _ algebra:GroupGraphPattern() { rule Modify() -> Vec<GraphUpdateOperation> = with:Modify_with()? _ Modify_clear() c:Modify_clauses() _ u:(UsingClause() ** (_)) _ i("WHERE") _ pattern:GroupGraphPattern() {
let (delete, insert) = c; let (delete, insert) = c;
let mut delete = delete.unwrap_or_else(Vec::new); let mut delete = delete.unwrap_or_else(Vec::new);
let mut insert = insert.unwrap_or_else(Vec::new); let mut insert = insert.unwrap_or_else(Vec::new);
let mut algebra = algebra; let mut pattern = pattern;
if let Some(with) = with { if let Some(with) = with {
// We inject WITH everywhere // We inject WITH everywhere
@ -969,7 +1048,7 @@ parser! {
} else { } else {
q q
}).collect(); }).collect();
algebra = GraphPattern::Graph(with.into(), Box::new(algebra)); pattern = GraphPattern::Graph { graph_name: with.into(), inner: Box::new(pattern) };
} }
let mut using = QueryDataset::default(); let mut using = QueryDataset::default();
@ -992,7 +1071,7 @@ parser! {
delete, delete,
insert, insert,
using, using,
algebra pattern: Box::new(pattern)
}] }]
} }
rule Modify_with() -> NamedNode = i("WITH") _ i:iri() _ { i } rule Modify_with() -> NamedNode = i("WITH") _ i:iri() _ { i }
@ -1022,10 +1101,10 @@ parser! {
} }
//[45] //[45]
rule GraphOrDefault() -> NamedOrDefaultGraphTarget = i("DEFAULT") { rule GraphOrDefault() -> Option<NamedNode> = i("DEFAULT") {
NamedOrDefaultGraphTarget::DefaultGraph None
} / (i("GRAPH") _)? g:iri() { } / (i("GRAPH") _)? g:iri() {
NamedOrDefaultGraphTarget::NamedNode(g) Some(g)
} }
//[46] //[46]
@ -1061,7 +1140,7 @@ parser! {
rule TriplesTemplate() -> Vec<TriplePattern> = h:TriplesSameSubject() _ t:TriplesTemplate_tail()? { rule TriplesTemplate() -> Vec<TriplePattern> = h:TriplesSameSubject() _ t:TriplesTemplate_tail()? {
let mut triples = h; let mut triples = h;
if let Some(l) = t { if let Some(l) = t {
triples.extend_from_slice(&l) triples.extend(l)
} }
triples triples
} }
@ -1076,22 +1155,22 @@ parser! {
//[54] //[54]
rule GroupGraphPatternSub() -> GraphPattern = a:TriplesBlock()? _ b:GroupGraphPatternSub_item()* { rule GroupGraphPatternSub() -> GraphPattern = a:TriplesBlock()? _ b:GroupGraphPatternSub_item()* {
let mut p = a.map_or_else(Vec::default, |v| vec![PartialGraphPattern::Other(GraphPattern::BGP(v))]); let mut p = a.map_or_else(Vec::default, |v| vec![PartialGraphPattern::Other(build_bgp(v))]);
for v in b { for v in b {
p.extend_from_slice(&v) p.extend(v)
} }
let mut filter: Option<Expression> = None; let mut filter: Option<Expression> = None;
let mut g = GraphPattern::default(); let mut g = GraphPattern::default();
for e in p { for e in p {
match e { match e {
PartialGraphPattern::Optional(p, f) => { PartialGraphPattern::Optional(p, f) => {
g = GraphPattern::LeftJoin(Box::new(g), Box::new(p), f) g = GraphPattern::LeftJoin { left: Box::new(g), right: Box::new(p), expr: f }
} }
PartialGraphPattern::Minus(p) => { PartialGraphPattern::Minus(p) => {
g = GraphPattern::Minus(Box::new(g), Box::new(p)) g = GraphPattern::Minus { left: Box::new(g), right: Box::new(p) }
} }
PartialGraphPattern::Bind(expr, var) => { PartialGraphPattern::Bind(expr, var) => {
g = GraphPattern::Extend(Box::new(g), var, expr) g = GraphPattern::Extend { inner: Box::new(g), var, expr }
} }
PartialGraphPattern::Filter(expr) => filter = Some(if let Some(f) = filter { PartialGraphPattern::Filter(expr) => filter = Some(if let Some(f) = filter {
Expression::And(Box::new(f), Box::new(expr)) Expression::And(Box::new(f), Box::new(expr))
@ -1106,8 +1185,8 @@ parser! {
state.used_bnodes.extend(state.currently_used_bnodes.iter().cloned()); state.used_bnodes.extend(state.currently_used_bnodes.iter().cloned());
state.currently_used_bnodes.clear(); state.currently_used_bnodes.clear();
if let Some(filter) = filter { if let Some(expr) = filter {
GraphPattern::Filter(filter, Box::new(g)) GraphPattern::Filter { expr, inner: Box::new(g) }
} else { } else {
g g
} }
@ -1115,7 +1194,7 @@ parser! {
rule GroupGraphPatternSub_item() -> Vec<PartialGraphPattern> = a:GraphPatternNotTriples() _ ("." _)? b:TriplesBlock()? _ { rule GroupGraphPatternSub_item() -> Vec<PartialGraphPattern> = a:GraphPatternNotTriples() _ ("." _)? b:TriplesBlock()? _ {
let mut result = vec![a]; let mut result = vec![a];
if let Some(v) = b { if let Some(v) = b {
result.push(PartialGraphPattern::Other(GraphPattern::BGP(v))); result.push(PartialGraphPattern::Other(build_bgp(v)));
} }
result result
} }
@ -1124,7 +1203,7 @@ parser! {
rule TriplesBlock() -> Vec<TripleOrPathPattern> = h:TriplesSameSubjectPath() _ t:TriplesBlock_tail()? { rule TriplesBlock() -> Vec<TripleOrPathPattern> = h:TriplesSameSubjectPath() _ t:TriplesBlock_tail()? {
let mut triples = h; let mut triples = h;
if let Some(l) = t { if let Some(l) = t {
triples.extend_from_slice(&l) triples.extend(l)
} }
triples triples
} }
@ -1137,22 +1216,22 @@ parser! {
//[57] //[57]
rule OptionalGraphPattern() -> PartialGraphPattern = i("OPTIONAL") _ p:GroupGraphPattern() { rule OptionalGraphPattern() -> PartialGraphPattern = i("OPTIONAL") _ p:GroupGraphPattern() {
if let GraphPattern::Filter(f, p) = p { if let GraphPattern::Filter { expr, inner } = p {
PartialGraphPattern::Optional(*p, Some(f)) PartialGraphPattern::Optional(*inner, Some(expr))
} else { } else {
PartialGraphPattern::Optional(p, None) PartialGraphPattern::Optional(p, None)
} }
} }
//[58] //[58]
rule GraphGraphPattern() -> PartialGraphPattern = i("GRAPH") _ g:VarOrIri() _ p:GroupGraphPattern() { rule GraphGraphPattern() -> PartialGraphPattern = i("GRAPH") _ graph_name:VarOrIri() _ p:GroupGraphPattern() {
PartialGraphPattern::Other(GraphPattern::Graph(g, Box::new(p))) PartialGraphPattern::Other(GraphPattern::Graph { graph_name, inner: Box::new(p) })
} }
//[59] //[59]
rule ServiceGraphPattern() -> PartialGraphPattern = rule ServiceGraphPattern() -> PartialGraphPattern =
i("SERVICE") _ i("SILENT") _ s:VarOrIri() _ p:GroupGraphPattern() { PartialGraphPattern::Other(GraphPattern::Service(s, Box::new(p), true)) } / i("SERVICE") _ i("SILENT") _ name:VarOrIri() _ p:GroupGraphPattern() { PartialGraphPattern::Other(GraphPattern::Service { name, pattern: Box::new(p), silent: true }) } /
i("SERVICE") _ s:VarOrIri() _ p:GroupGraphPattern() { PartialGraphPattern::Other(GraphPattern::Service(s, Box::new(p), false)) } i("SERVICE") _ name:VarOrIri() _ p:GroupGraphPattern() { PartialGraphPattern::Other(GraphPattern::Service{ name, pattern: Box::new(p), silent: true }) }
//[60] //[60]
rule Bind() -> PartialGraphPattern = i("BIND") _ "(" _ e:Expression() _ i("AS") _ v:Var() _ ")" { rule Bind() -> PartialGraphPattern = i("BIND") _ "(" _ e:Expression() _ i("AS") _ v:Var() _ ")" {
@ -1164,18 +1243,18 @@ parser! {
//[62] //[62]
rule DataBlock() -> GraphPattern = l:(InlineDataOneVar() / InlineDataFull()) { rule DataBlock() -> GraphPattern = l:(InlineDataOneVar() / InlineDataFull()) {
GraphPattern::Data(l) GraphPattern::Table { variables: l.0, rows: l.1 }
} }
//[63] //[63]
rule InlineDataOneVar() -> StaticBindings = var:Var() _ "{" _ d:InlineDataOneVar_value()* "}" { rule InlineDataOneVar() -> (Vec<Variable>, Vec<Vec<Option<Term>>>) = var:Var() _ "{" _ d:InlineDataOneVar_value()* "}" {
StaticBindings::new(vec![var], d) (vec![var], d)
} }
rule InlineDataOneVar_value() -> Vec<Option<Term>> = t:DataBlockValue() _ { vec![t] } rule InlineDataOneVar_value() -> Vec<Option<Term>> = t:DataBlockValue() _ { vec![t] }
//[64] //[64]
rule InlineDataFull() -> StaticBindings = "(" _ vars:InlineDataFull_var()* _ ")" _ "{" _ val:InlineDataFull_values()* "}" { rule InlineDataFull() -> (Vec<Variable>, Vec<Vec<Option<Term>>>) = "(" _ vars:InlineDataFull_var()* _ ")" _ "{" _ val:InlineDataFull_values()* "}" {
StaticBindings::new(vars, val) (vars, val)
} }
rule InlineDataFull_var() -> Variable = v:Var() _ { v } rule InlineDataFull_var() -> Variable = v:Var() _ { v }
rule InlineDataFull_values() -> Vec<Option<Term>> = "(" _ v:InlineDataFull_value()* _ ")" _ { v } rule InlineDataFull_values() -> Vec<Option<Term>> = "(" _ v:InlineDataFull_value()* _ ")" _ { v }
@ -1197,7 +1276,7 @@ parser! {
//[67] //[67]
rule GroupOrUnionGraphPattern() -> PartialGraphPattern = p:GroupOrUnionGraphPattern_item() **<1,> (i("UNION") _) {? rule GroupOrUnionGraphPattern() -> PartialGraphPattern = p:GroupOrUnionGraphPattern_item() **<1,> (i("UNION") _) {?
not_empty_fold(p.into_iter(), |a, b| { not_empty_fold(p.into_iter(), |a, b| {
GraphPattern::Union(Box::new(a), Box::new(b)) GraphPattern::Union { left: Box::new(a), right: Box::new(b) }
}).map(PartialGraphPattern::Other) }).map(PartialGraphPattern::Other)
} }
rule GroupOrUnionGraphPattern_item() -> GraphPattern = p:GroupGraphPattern() _ { p } rule GroupOrUnionGraphPattern_item() -> GraphPattern = p:GroupGraphPattern() _ { p }
@ -1249,7 +1328,7 @@ parser! {
} / } /
s:TriplesNode() _ po:PropertyList() { s:TriplesNode() _ po:PropertyList() {
let mut patterns = s.patterns; let mut patterns = s.patterns;
patterns.extend_from_slice(&po.patterns); patterns.extend(po.patterns);
for (p, os) in po.focus { for (p, os) in po.focus {
for o in os { for o in os {
patterns.push(TriplePattern::new(s.focus.clone(), p.clone(), o)) patterns.push(TriplePattern::new(s.focus.clone(), p.clone(), o))
@ -1267,7 +1346,7 @@ parser! {
rule PropertyListNotEmpty() -> FocusedTriplePattern<Vec<(NamedNodeOrVariable,Vec<TermOrVariable>)>> = l:PropertyListNotEmpty_item() **<1,> (";" _) { rule PropertyListNotEmpty() -> FocusedTriplePattern<Vec<(NamedNodeOrVariable,Vec<TermOrVariable>)>> = l:PropertyListNotEmpty_item() **<1,> (";" _) {
l.into_iter().fold(FocusedTriplePattern::<Vec<(NamedNodeOrVariable,Vec<TermOrVariable>)>>::default(), |mut a, b| { l.into_iter().fold(FocusedTriplePattern::<Vec<(NamedNodeOrVariable,Vec<TermOrVariable>)>>::default(), |mut a, b| {
a.focus.push(b.focus); a.focus.push(b.focus);
a.patterns.extend_from_slice(&b.patterns); a.patterns.extend(b.patterns);
a a
}) })
} }
@ -1279,7 +1358,7 @@ parser! {
} }
//[78] //[78]
rule Verb() -> NamedNodeOrVariable = VarOrIri() / "a" { rdf::TYPE.into() } rule Verb() -> NamedNodeOrVariable = VarOrIri() / "a" { rdf::TYPE.into_owned().into() }
//[79] //[79]
rule ObjectList() -> FocusedTriplePattern<Vec<TermOrVariable>> = o:ObjectList_item() **<1,> ("," _) { rule ObjectList() -> FocusedTriplePattern<Vec<TermOrVariable>> = o:ObjectList_item() **<1,> ("," _) {
@ -1307,7 +1386,7 @@ parser! {
} / } /
s:TriplesNodePath() _ po:PropertyListPath() { s:TriplesNodePath() _ po:PropertyListPath() {
let mut patterns = s.patterns; let mut patterns = s.patterns;
patterns.extend_from_slice(&po.patterns); patterns.extend(po.patterns);
for (p, os) in po.focus { for (p, os) in po.focus {
for o in os { for o in os {
add_to_triple_or_path_patterns(s.focus.clone(), p.clone(), o, &mut patterns); add_to_triple_or_path_patterns(s.focus.clone(), p.clone(), o, &mut patterns);
@ -1356,7 +1435,7 @@ parser! {
rule ObjectListPath() -> FocusedTripleOrPathPattern<Vec<TermOrVariable>> = o:ObjectPath_item() **<1,> ("," _) { rule ObjectListPath() -> FocusedTripleOrPathPattern<Vec<TermOrVariable>> = o:ObjectPath_item() **<1,> ("," _) {
o.into_iter().fold(FocusedTripleOrPathPattern::<Vec<TermOrVariable>>::default(), |mut a, b| { o.into_iter().fold(FocusedTripleOrPathPattern::<Vec<TermOrVariable>>::default(), |mut a, b| {
a.focus.push(b.focus); a.focus.push(b.focus);
a.patterns.extend_from_slice(&b.patterns); a.patterns.extend(b.patterns);
a a
}) })
} }
@ -1366,45 +1445,45 @@ parser! {
rule ObjectPath() -> FocusedTripleOrPathPattern<TermOrVariable> = GraphNodePath() rule ObjectPath() -> FocusedTripleOrPathPattern<TermOrVariable> = GraphNodePath()
//[88] //[88]
rule Path() -> PropertyPath = PathAlternative() rule Path() -> PropertyPathExpression = PathAlternative()
//[89] //[89]
rule PathAlternative() -> PropertyPath = p:PathAlternative_item() **<1,> ("|" _) {? rule PathAlternative() -> PropertyPathExpression = p:PathAlternative_item() **<1,> ("|" _) {?
not_empty_fold(p.into_iter(), |a, b| { not_empty_fold(p.into_iter(), |a, b| {
PropertyPath::AlternativePath(Box::new(a), Box::new(b)) PropertyPathExpression::Alternative(Box::new(a), Box::new(b))
}) })
} }
rule PathAlternative_item() -> PropertyPath = p:PathSequence() _ { p } rule PathAlternative_item() -> PropertyPathExpression = p:PathSequence() _ { p }
//[90] //[90]
rule PathSequence() -> PropertyPath = p:PathSequence_item() **<1,> ("/" _) {? rule PathSequence() -> PropertyPathExpression = p:PathSequence_item() **<1,> ("/" _) {?
not_empty_fold(p.into_iter(), |a, b| { not_empty_fold(p.into_iter(), |a, b| {
PropertyPath::SequencePath(Box::new(a), Box::new(b)) PropertyPathExpression::Sequence(Box::new(a), Box::new(b))
}) })
} }
rule PathSequence_item() -> PropertyPath = p:PathEltOrInverse() _ { p } rule PathSequence_item() -> PropertyPathExpression = p:PathEltOrInverse() _ { p }
//[91] //[91]
rule PathElt() -> PropertyPath = rule PathElt() -> PropertyPathExpression =
p:PathPrimary() "?" { PropertyPath::ZeroOrOnePath(Box::new(p)) } / //TODO: allow space before "?" p:PathPrimary() "?" { PropertyPathExpression::ZeroOrOne(Box::new(p)) } / //TODO: allow space before "?"
p:PathPrimary() _ "*" { PropertyPath::ZeroOrMorePath(Box::new(p)) } / p:PathPrimary() _ "*" { PropertyPathExpression::ZeroOrMore(Box::new(p)) } /
p:PathPrimary() _ "+" { PropertyPath::OneOrMorePath(Box::new(p)) } / p:PathPrimary() _ "+" { PropertyPathExpression::OneOrMore(Box::new(p)) } /
PathPrimary() PathPrimary()
//[92] //[92]
rule PathEltOrInverse() -> PropertyPath = rule PathEltOrInverse() -> PropertyPathExpression =
"^" _ p:PathElt() { PropertyPath::InversePath(Box::new(p)) } / "^" _ p:PathElt() { PropertyPathExpression::Reverse(Box::new(p)) } /
PathElt() PathElt()
//[94] //[94]
rule PathPrimary() -> PropertyPath = rule PathPrimary() -> PropertyPathExpression =
v:iri() { v.into() } / v:iri() { v.into() } /
"a" { NamedNode::from(rdf::TYPE).into() } / "a" { rdf::TYPE.into_owned().into() } /
"!" _ p:PathNegatedPropertySet() { p } / "!" _ p:PathNegatedPropertySet() { p } /
"(" _ p:Path() _ ")" { p } "(" _ p:Path() _ ")" { p }
//[95] //[95]
rule PathNegatedPropertySet() -> PropertyPath = rule PathNegatedPropertySet() -> PropertyPathExpression =
"(" _ p:PathNegatedPropertySet_item() **<1,> ("|" _) ")" { "(" _ p:PathNegatedPropertySet_item() **<1,> ("|" _) ")" {
let mut direct = Vec::default(); let mut direct = Vec::default();
let mut inverse = Vec::default(); let mut inverse = Vec::default();
@ -1415,20 +1494,20 @@ parser! {
} }
} }
if inverse.is_empty() { if inverse.is_empty() {
PropertyPath::NegatedPropertySet(direct) PropertyPathExpression::NegatedPropertySet(direct)
} else if direct.is_empty() { } else if direct.is_empty() {
PropertyPath::InversePath(Box::new(PropertyPath::NegatedPropertySet(inverse))) PropertyPathExpression::Reverse(Box::new(PropertyPathExpression::NegatedPropertySet(inverse)))
} else { } else {
PropertyPath::AlternativePath( PropertyPathExpression::Alternative(
Box::new(PropertyPath::NegatedPropertySet(direct)), Box::new(PropertyPathExpression::NegatedPropertySet(direct)),
Box::new(PropertyPath::InversePath(Box::new(PropertyPath::NegatedPropertySet(inverse)))) Box::new(PropertyPathExpression::Reverse(Box::new(PropertyPathExpression::NegatedPropertySet(inverse))))
) )
} }
} / } /
p:PathOneInPropertySet() { p:PathOneInPropertySet() {
match p { match p {
Either::Left(a) => PropertyPath::NegatedPropertySet(vec![a]), Either::Left(a) => PropertyPathExpression::NegatedPropertySet(vec![a]),
Either::Right(b) => PropertyPath::InversePath(Box::new(PropertyPath::NegatedPropertySet(vec![b]))), Either::Right(b) => PropertyPathExpression::Reverse(Box::new(PropertyPathExpression::NegatedPropertySet(vec![b]))),
} }
} }
rule PathNegatedPropertySet_item() -> Either<NamedNode,NamedNode> = p:PathOneInPropertySet() _ { p } rule PathNegatedPropertySet_item() -> Either<NamedNode,NamedNode> = p:PathOneInPropertySet() _ { p }
@ -1436,9 +1515,9 @@ parser! {
//[96] //[96]
rule PathOneInPropertySet() -> Either<NamedNode,NamedNode> = rule PathOneInPropertySet() -> Either<NamedNode,NamedNode> =
"^" _ v:iri() { Either::Right(v) } / "^" _ v:iri() { Either::Right(v) } /
"^" _ "a" { Either::Right(rdf::TYPE.into()) } / "^" _ "a" { Either::Right(rdf::TYPE.into_owned()) } /
v:iri() { Either::Left(v) } / v:iri() { Either::Left(v) } /
"a" { Either::Left(rdf::TYPE.into()) } "a" { Either::Left(rdf::TYPE.into_owned()) }
//[98] //[98]
rule TriplesNode() -> FocusedTriplePattern<TermOrVariable> = Collection() / BlankNodePropertyList() rule TriplesNode() -> FocusedTriplePattern<TermOrVariable> = Collection() / BlankNodePropertyList()
@ -1479,11 +1558,11 @@ parser! {
//[102] //[102]
rule Collection() -> FocusedTriplePattern<TermOrVariable> = "(" _ o:Collection_item()+ ")" { rule Collection() -> FocusedTriplePattern<TermOrVariable> = "(" _ o:Collection_item()+ ")" {
let mut patterns: Vec<TriplePattern> = Vec::default(); let mut patterns: Vec<TriplePattern> = Vec::default();
let mut current_list_node = TermOrVariable::from(rdf::NIL); let mut current_list_node = TermOrVariable::from(rdf::NIL.into_owned());
for objWithPatterns in o.into_iter().rev() { for objWithPatterns in o.into_iter().rev() {
let new_blank_node = TermOrVariable::from(BlankNode::default()); let new_blank_node = TermOrVariable::from(BlankNode::default());
patterns.push(TriplePattern::new(new_blank_node.clone(), rdf::FIRST, objWithPatterns.focus.clone())); patterns.push(TriplePattern::new(new_blank_node.clone(), rdf::FIRST.into_owned(), objWithPatterns.focus.clone()));
patterns.push(TriplePattern::new(new_blank_node.clone(), rdf::REST, current_list_node)); patterns.push(TriplePattern::new(new_blank_node.clone(), rdf::REST.into_owned(), current_list_node));
current_list_node = new_blank_node; current_list_node = new_blank_node;
patterns.extend_from_slice(&objWithPatterns.patterns); patterns.extend_from_slice(&objWithPatterns.patterns);
} }
@ -1497,13 +1576,13 @@ parser! {
//[103] //[103]
rule CollectionPath() -> FocusedTripleOrPathPattern<TermOrVariable> = "(" _ o:CollectionPath_item()+ _ ")" { rule CollectionPath() -> FocusedTripleOrPathPattern<TermOrVariable> = "(" _ o:CollectionPath_item()+ _ ")" {
let mut patterns: Vec<TripleOrPathPattern> = Vec::default(); let mut patterns: Vec<TripleOrPathPattern> = Vec::default();
let mut current_list_node = TermOrVariable::from(rdf::NIL); let mut current_list_node = TermOrVariable::from(rdf::NIL.into_owned());
for objWithPatterns in o.into_iter().rev() { for objWithPatterns in o.into_iter().rev() {
let new_blank_node = TermOrVariable::from(BlankNode::default()); let new_blank_node = TermOrVariable::from(BlankNode::default());
patterns.push(TriplePattern::new(new_blank_node.clone(), rdf::FIRST, objWithPatterns.focus.clone()).into()); patterns.push(TriplePattern::new(new_blank_node.clone(), rdf::FIRST.into_owned(), objWithPatterns.focus.clone()).into());
patterns.push(TriplePattern::new(new_blank_node.clone(), rdf::REST, current_list_node).into()); patterns.push(TriplePattern::new(new_blank_node.clone(), rdf::REST.into_owned(), current_list_node).into());
current_list_node = new_blank_node; current_list_node = new_blank_node;
patterns.extend_from_slice(&objWithPatterns.patterns); patterns.extend(objWithPatterns.patterns);
} }
FocusedTripleOrPathPattern { FocusedTripleOrPathPattern {
focus: current_list_node, focus: current_list_node,
@ -1565,13 +1644,13 @@ parser! {
//[114] //[114]
rule RelationalExpression() -> Expression = a:NumericExpression() _ o: RelationalExpression_inner()? { match o { rule RelationalExpression() -> Expression = a:NumericExpression() _ o: RelationalExpression_inner()? { match o {
Some(("=", Some(b), None)) => Expression::Equal(Box::new(a), Box::new(b)), Some(("=", Some(b), None)) => Expression::Equal(Box::new(a), Box::new(b)),
Some(("!=", Some(b), None)) => Expression::NotEqual(Box::new(a), Box::new(b)), Some(("!=", Some(b), None)) => Expression::Not(Box::new(Expression::Equal(Box::new(a), Box::new(b)))),
Some((">", Some(b), None)) => Expression::Greater(Box::new(a), Box::new(b)), Some((">", Some(b), None)) => Expression::Greater(Box::new(a), Box::new(b)),
Some((">=", Some(b), None)) => Expression::GreaterOrEq(Box::new(a), Box::new(b)), Some((">=", Some(b), None)) => Expression::GreaterOrEqual(Box::new(a), Box::new(b)),
Some(("<", Some(b), None)) => Expression::Lower(Box::new(a), Box::new(b)), Some(("<", Some(b), None)) => Expression::Less(Box::new(a), Box::new(b)),
Some(("<=", Some(b), None)) => Expression::LowerOrEq(Box::new(a), Box::new(b)), Some(("<=", Some(b), None)) => Expression::LessOrEqual(Box::new(a), Box::new(b)),
Some(("IN", None, Some(l))) => Expression::In(Box::new(a), l), Some(("IN", None, Some(l))) => Expression::In(Box::new(a), l),
Some(("NOT IN", None, Some(l))) => Expression::NotIn(Box::new(a), l), Some(("NOT IN", None, Some(l))) => Expression::Not(Box::new(Expression::In(Box::new(a), l))),
Some(_) => unreachable!(), Some(_) => unreachable!(),
None => a None => a
} } } }
@ -1586,7 +1665,7 @@ parser! {
//[116] //[116]
rule AdditiveExpression() -> Expression = a:MultiplicativeExpression() _ o:AdditiveExpression_inner()? { match o { rule AdditiveExpression() -> Expression = a:MultiplicativeExpression() _ o:AdditiveExpression_inner()? { match o {
Some(("+", b)) => Expression::Add(Box::new(a), Box::new(b)), Some(("+", b)) => Expression::Add(Box::new(a), Box::new(b)),
Some(("-", b)) => Expression::Sub(Box::new(a), Box::new(b)), Some(("-", b)) => Expression::Subtract(Box::new(a), Box::new(b)),
Some(_) => unreachable!(), Some(_) => unreachable!(),
None => a, None => a,
} } } }
@ -1596,8 +1675,8 @@ parser! {
//[117] //[117]
rule MultiplicativeExpression() -> Expression = a:UnaryExpression() _ o: MultiplicativeExpression_inner()? { match o { rule MultiplicativeExpression() -> Expression = a:UnaryExpression() _ o: MultiplicativeExpression_inner()? { match o {
Some(("*", b)) => Expression::Mul(Box::new(a), Box::new(b)), Some(("*", b)) => Expression::Multiply(Box::new(a), Box::new(b)),
Some(("/", b)) => Expression::Div(Box::new(a), Box::new(b)), Some(("/", b)) => Expression::Divide(Box::new(a), Box::new(b)),
Some(_) => unreachable!(), Some(_) => unreachable!(),
None => a None => a
} } } }
@ -1607,7 +1686,7 @@ parser! {
//[118] //[118]
rule UnaryExpression() -> Expression = s: $("!" / "+" / "-")? _ e:PrimaryExpression() { match s { rule UnaryExpression() -> Expression = s: $("!" / "+" / "-")? _ e:PrimaryExpression() { match s {
Some("!") => Expression::UnaryNot(Box::new(e)), Some("!") => Expression::Not(Box::new(e)),
Some("+") => Expression::UnaryPlus(Box::new(e)), Some("+") => Expression::UnaryPlus(Box::new(e)),
Some("-") => Expression::UnaryMinus(Box::new(e)), Some("-") => Expression::UnaryMinus(Box::new(e)),
Some(_) => unreachable!(), Some(_) => unreachable!(),
@ -1671,11 +1750,11 @@ parser! {
i("SHA256") "(" _ e:Expression() _ ")" { Expression::FunctionCall(Function::SHA256, vec![e]) } / i("SHA256") "(" _ e:Expression() _ ")" { Expression::FunctionCall(Function::SHA256, vec![e]) } /
i("SHA384") "(" _ e:Expression() _ ")" { Expression::FunctionCall(Function::SHA384, vec![e]) } / i("SHA384") "(" _ e:Expression() _ ")" { Expression::FunctionCall(Function::SHA384, vec![e]) } /
i("SHA512") "(" _ e:Expression() _ ")" { Expression::FunctionCall(Function::SHA512, vec![e]) } / i("SHA512") "(" _ e:Expression() _ ")" { Expression::FunctionCall(Function::SHA512, vec![e]) } /
i("COALESCE") e:ExpressionList() { Expression::FunctionCall(Function::Coalesce, e) } / i("COALESCE") e:ExpressionList() { Expression::Coalesce(e) } /
i("IF") _ "(" _ a:Expression() _ "," _ b:Expression() _ "," _ c:Expression() _ ")" { Expression::FunctionCall(Function::If, vec![a, b, c]) } / i("IF") _ "(" _ a:Expression() _ "," _ b:Expression() _ "," _ c:Expression() _ ")" { Expression::If(Box::new(a), Box::new(b), Box::new(c)) } /
i("STRLANG") _ "(" _ a:Expression() _ "," _ b:Expression() _ ")" { Expression::FunctionCall(Function::StrLang, vec![a, b]) } / i("STRLANG") _ "(" _ a:Expression() _ "," _ b:Expression() _ ")" { Expression::FunctionCall(Function::StrLang, vec![a, b]) } /
i("STRDT") _ "(" _ a:Expression() _ "," _ b:Expression() _ ")" { Expression::FunctionCall(Function::StrDT, vec![a, b]) } / i("STRDT") _ "(" _ a:Expression() _ "," _ b:Expression() _ ")" { Expression::FunctionCall(Function::StrDT, vec![a, b]) } /
i("sameTerm") "(" _ a:Expression() _ "," _ b:Expression() _ ")" { Expression::FunctionCall(Function::SameTerm, vec![a, b]) } / i("sameTerm") "(" _ a:Expression() _ "," _ b:Expression() _ ")" { Expression::SameTerm(Box::new(a), Box::new(b)) } /
(i("isIRI") / i("isURI")) _ "(" _ e:Expression() _ ")" { Expression::FunctionCall(Function::IsIRI, vec![e]) } / (i("isIRI") / i("isURI")) _ "(" _ e:Expression() _ ")" { Expression::FunctionCall(Function::IsIRI, vec![e]) } /
i("isBLANK") "(" _ e:Expression() _ ")" { Expression::FunctionCall(Function::IsBlank, vec![e]) } / i("isBLANK") "(" _ e:Expression() _ ")" { Expression::FunctionCall(Function::IsBlank, vec![e]) } /
i("isLITERAL") "(" _ e:Expression() _ ")" { Expression::FunctionCall(Function::IsLiteral, vec![e]) } / i("isLITERAL") "(" _ e:Expression() _ ")" { Expression::FunctionCall(Function::IsLiteral, vec![e]) } /
@ -1704,28 +1783,28 @@ parser! {
rule ExistsFunc() -> Expression = i("EXISTS") _ p:GroupGraphPattern() { Expression::Exists(Box::new(p)) } rule ExistsFunc() -> Expression = i("EXISTS") _ p:GroupGraphPattern() { Expression::Exists(Box::new(p)) }
//[126] //[126]
rule NotExistsFunc() -> Expression = i("NOT") _ i("EXISTS") _ p:GroupGraphPattern() { Expression::UnaryNot(Box::new(Expression::Exists(Box::new(p)))) } rule NotExistsFunc() -> Expression = i("NOT") _ i("EXISTS") _ p:GroupGraphPattern() { Expression::Not(Box::new(Expression::Exists(Box::new(p)))) }
//[127] //[127]
rule Aggregate() -> Aggregation = rule Aggregate() -> SetFunction =
i("COUNT") _ "(" _ i("DISTINCT") _ "*" _ ")" { Aggregation::Count(None, true) } / i("COUNT") _ "(" _ i("DISTINCT") _ "*" _ ")" { SetFunction::Count { expr: None, distinct: true } } /
i("COUNT") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { Aggregation::Count(Some(Box::new(e)), true) } / i("COUNT") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { SetFunction::Count { expr: Some(Box::new(e)), distinct: true } } /
i("COUNT") _ "(" _ "*" _ ")" { Aggregation::Count(None, false) } / i("COUNT") _ "(" _ "*" _ ")" { SetFunction::Count { expr: None, distinct: false } } /
i("COUNT") _ "(" _ e:Expression() _ ")" { Aggregation::Count(Some(Box::new(e)), false) } / i("COUNT") _ "(" _ e:Expression() _ ")" { SetFunction::Count { expr: Some(Box::new(e)), distinct: false } } /
i("SUM") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { Aggregation::Sum(Box::new(e), true) } / i("SUM") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { SetFunction::Sum { expr: Box::new(e), distinct: true } } /
i("SUM") _ "(" _ e:Expression() _ ")" { Aggregation::Sum(Box::new(e), false) } / i("SUM") _ "(" _ e:Expression() _ ")" { SetFunction::Sum { expr: Box::new(e), distinct: false } } /
i("MIN") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { Aggregation::Min(Box::new(e), true) } / i("MIN") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { SetFunction::Min { expr: Box::new(e), distinct: true } } /
i("MIN") _ "(" _ e:Expression() _ ")" { Aggregation::Min(Box::new(e), false) } / i("MIN") _ "(" _ e:Expression() _ ")" { SetFunction::Min { expr: Box::new(e), distinct: false } } /
i("MAX") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { Aggregation::Max(Box::new(e), true) } / i("MAX") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { SetFunction::Max { expr: Box::new(e), distinct: true } } /
i("MAX") _ "(" _ e:Expression() _ ")" { Aggregation::Max(Box::new(e), false) } / i("MAX") _ "(" _ e:Expression() _ ")" { SetFunction::Max { expr: Box::new(e), distinct: false } } /
i("AVG") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { Aggregation::Avg(Box::new(e), true) } / i("AVG") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { SetFunction::Avg { expr: Box::new(e), distinct: true } } /
i("AVG") _ "(" _ e:Expression() _ ")" { Aggregation::Avg(Box::new(e), false) } / i("AVG") _ "(" _ e:Expression() _ ")" { SetFunction::Avg { expr: Box::new(e), distinct: false } } /
i("SAMPLE") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { Aggregation::Sample(Box::new(e), true) } / i("SAMPLE") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { SetFunction::Sample { expr: Box::new(e), distinct: true } } /
i("SAMPLE") _ "(" _ e:Expression() _ ")" { Aggregation::Sample(Box::new(e), false) } / i("SAMPLE") _ "(" _ e:Expression() _ ")" { SetFunction::Sample { expr: Box::new(e), distinct: false } } /
i("GROUP_CONCAT") _ "(" _ i("DISTINCT") _ e:Expression() _ ";" _ i("SEPARATOR") _ "=" _ s:String() _ ")" { Aggregation::GroupConcat(Box::new(e), true, Some(s)) } / i("GROUP_CONCAT") _ "(" _ i("DISTINCT") _ e:Expression() _ ";" _ i("SEPARATOR") _ "=" _ s:String() _ ")" { SetFunction::GroupConcat { expr: Box::new(e), distinct: true, separator: Some(s) } } /
i("GROUP_CONCAT") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { Aggregation::GroupConcat(Box::new(e), true, None) } / i("GROUP_CONCAT") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { SetFunction::GroupConcat { expr: Box::new(e), distinct: true, separator: None } } /
i("GROUP_CONCAT") _ "(" _ e:Expression() _ ";" _ i("SEPARATOR") _ "=" _ s:String() _ ")" { Aggregation::GroupConcat(Box::new(e), true, Some(s)) } / i("GROUP_CONCAT") _ "(" _ e:Expression() _ ";" _ i("SEPARATOR") _ "=" _ s:String() _ ")" { SetFunction::GroupConcat { expr: Box::new(e), distinct: true, separator: Some(s) } } /
i("GROUP_CONCAT") _ "(" _ e:Expression() _ ")" { Aggregation::GroupConcat(Box::new(e), false, None) } i("GROUP_CONCAT") _ "(" _ e:Expression() _ ")" { SetFunction::GroupConcat { expr: Box::new(e), distinct: false, separator: None } }
//[128] //[128]
rule iriOrFunction() -> Expression = i: iri() _ a: ArgList()? { rule iriOrFunction() -> Expression = i: iri() _ a: ArgList()? {

@ -216,19 +216,18 @@ pub enum PlanExpression<I: StrId> {
Or(Box<PlanExpression<I>>, Box<PlanExpression<I>>), Or(Box<PlanExpression<I>>, Box<PlanExpression<I>>),
And(Box<PlanExpression<I>>, Box<PlanExpression<I>>), And(Box<PlanExpression<I>>, Box<PlanExpression<I>>),
Equal(Box<PlanExpression<I>>, Box<PlanExpression<I>>), Equal(Box<PlanExpression<I>>, Box<PlanExpression<I>>),
NotEqual(Box<PlanExpression<I>>, Box<PlanExpression<I>>),
Greater(Box<PlanExpression<I>>, Box<PlanExpression<I>>), Greater(Box<PlanExpression<I>>, Box<PlanExpression<I>>),
GreaterOrEq(Box<PlanExpression<I>>, Box<PlanExpression<I>>), GreaterOrEqual(Box<PlanExpression<I>>, Box<PlanExpression<I>>),
Lower(Box<PlanExpression<I>>, Box<PlanExpression<I>>), Less(Box<PlanExpression<I>>, Box<PlanExpression<I>>),
LowerOrEq(Box<PlanExpression<I>>, Box<PlanExpression<I>>), LessOrEqual(Box<PlanExpression<I>>, Box<PlanExpression<I>>),
In(Box<PlanExpression<I>>, Vec<PlanExpression<I>>), In(Box<PlanExpression<I>>, Vec<PlanExpression<I>>),
Add(Box<PlanExpression<I>>, Box<PlanExpression<I>>), Add(Box<PlanExpression<I>>, Box<PlanExpression<I>>),
Sub(Box<PlanExpression<I>>, Box<PlanExpression<I>>), Subtract(Box<PlanExpression<I>>, Box<PlanExpression<I>>),
Mul(Box<PlanExpression<I>>, Box<PlanExpression<I>>), Multiply(Box<PlanExpression<I>>, Box<PlanExpression<I>>),
Div(Box<PlanExpression<I>>, Box<PlanExpression<I>>), Divide(Box<PlanExpression<I>>, Box<PlanExpression<I>>),
UnaryPlus(Box<PlanExpression<I>>), UnaryPlus(Box<PlanExpression<I>>),
UnaryMinus(Box<PlanExpression<I>>), UnaryMinus(Box<PlanExpression<I>>),
UnaryNot(Box<PlanExpression<I>>), Not(Box<PlanExpression<I>>),
Str(Box<PlanExpression<I>>), Str(Box<PlanExpression<I>>),
Lang(Box<PlanExpression<I>>), Lang(Box<PlanExpression<I>>),
LangMatches(Box<PlanExpression<I>>, Box<PlanExpression<I>>), LangMatches(Box<PlanExpression<I>>, Box<PlanExpression<I>>),
@ -324,7 +323,7 @@ impl<I: StrId> PlanExpression<I> {
| PlanExpression::BNode(None) => (), | PlanExpression::BNode(None) => (),
PlanExpression::UnaryPlus(e) PlanExpression::UnaryPlus(e)
| PlanExpression::UnaryMinus(e) | PlanExpression::UnaryMinus(e)
| PlanExpression::UnaryNot(e) | PlanExpression::Not(e)
| PlanExpression::BNode(Some(e)) | PlanExpression::BNode(Some(e))
| PlanExpression::Str(e) | PlanExpression::Str(e)
| PlanExpression::Lang(e) | PlanExpression::Lang(e)
@ -370,15 +369,14 @@ impl<I: StrId> PlanExpression<I> {
PlanExpression::Or(a, b) PlanExpression::Or(a, b)
| PlanExpression::And(a, b) | PlanExpression::And(a, b)
| PlanExpression::Equal(a, b) | PlanExpression::Equal(a, b)
| PlanExpression::NotEqual(a, b)
| PlanExpression::Greater(a, b) | PlanExpression::Greater(a, b)
| PlanExpression::GreaterOrEq(a, b) | PlanExpression::GreaterOrEqual(a, b)
| PlanExpression::Lower(a, b) | PlanExpression::Less(a, b)
| PlanExpression::LowerOrEq(a, b) | PlanExpression::LessOrEqual(a, b)
| PlanExpression::Add(a, b) | PlanExpression::Add(a, b)
| PlanExpression::Sub(a, b) | PlanExpression::Subtract(a, b)
| PlanExpression::Mul(a, b) | PlanExpression::Multiply(a, b)
| PlanExpression::Div(a, b) | PlanExpression::Divide(a, b)
| PlanExpression::LangMatches(a, b) | PlanExpression::LangMatches(a, b)
| PlanExpression::Contains(a, b) | PlanExpression::Contains(a, b)
| PlanExpression::StrStarts(a, b) | PlanExpression::StrStarts(a, b)
@ -446,13 +444,13 @@ pub enum PlanAggregationFunction {
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum PlanPropertyPath<I: StrId> { pub enum PlanPropertyPath<I: StrId> {
PredicatePath(EncodedTerm<I>), Path(EncodedTerm<I>),
InversePath(Rc<PlanPropertyPath<I>>), Reverse(Rc<PlanPropertyPath<I>>),
SequencePath(Rc<PlanPropertyPath<I>>, Rc<PlanPropertyPath<I>>), Sequence(Rc<PlanPropertyPath<I>>, Rc<PlanPropertyPath<I>>),
AlternativePath(Rc<PlanPropertyPath<I>>, Rc<PlanPropertyPath<I>>), Alternative(Rc<PlanPropertyPath<I>>, Rc<PlanPropertyPath<I>>),
ZeroOrMorePath(Rc<PlanPropertyPath<I>>), ZeroOrMore(Rc<PlanPropertyPath<I>>),
OneOrMorePath(Rc<PlanPropertyPath<I>>), OneOrMore(Rc<PlanPropertyPath<I>>),
ZeroOrOnePath(Rc<PlanPropertyPath<I>>), ZeroOrOne(Rc<PlanPropertyPath<I>>),
NegatedPropertySet(Rc<Vec<EncodedTerm<I>>>), NegatedPropertySet(Rc<Vec<EncodedTerm<I>>>),
} }

@ -41,22 +41,54 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
) -> Result<PlanNode<E::StrId>, EvaluationError> { ) -> Result<PlanNode<E::StrId>, EvaluationError> {
Ok(match pattern { Ok(match pattern {
GraphPattern::BGP(p) => self.build_for_bgp(p, variables, graph_name)?, GraphPattern::BGP(p) => self.build_for_bgp(p, variables, graph_name)?,
GraphPattern::Join(a, b) => PlanNode::Join { GraphPattern::Path {
left: Rc::new(self.build_for_graph_pattern(a, variables, graph_name)?), subject,
right: Rc::new(self.build_for_graph_pattern(b, variables, graph_name)?), path,
object,
} => PlanNode::PathPatternJoin {
child: Rc::new(PlanNode::Init),
subject: self.pattern_value_from_term_or_variable(subject, variables)?,
path: Rc::new(self.build_for_path(path)?),
object: self.pattern_value_from_term_or_variable(object, variables)?,
graph_name,
}, },
GraphPattern::LeftJoin(a, b, e) => { GraphPattern::Join { left, right } => {
let left = self.build_for_graph_pattern(a, variables, graph_name)?; //TODO: improve
let right = self.build_for_graph_pattern(b, variables, graph_name)?; if let GraphPattern::Path {
subject,
path,
object,
} = right.as_ref()
{
let left = self.build_for_graph_pattern(left, variables, graph_name)?;
PlanNode::PathPatternJoin {
child: Rc::new(left),
subject: self.pattern_value_from_term_or_variable(subject, variables)?,
path: Rc::new(self.build_for_path(path)?),
object: self.pattern_value_from_term_or_variable(object, variables)?,
graph_name,
}
} else {
PlanNode::Join {
left: Rc::new(self.build_for_graph_pattern(left, variables, graph_name)?),
right: Rc::new(self.build_for_graph_pattern(right, variables, graph_name)?),
}
}
}
GraphPattern::LeftJoin { left, right, expr } => {
let left = self.build_for_graph_pattern(left, variables, graph_name)?;
let right = self.build_for_graph_pattern(right, variables, graph_name)?;
let mut possible_problem_vars = BTreeSet::new(); let mut possible_problem_vars = BTreeSet::new();
self.add_left_join_problematic_variables(&right, &mut possible_problem_vars); self.add_left_join_problematic_variables(&right, &mut possible_problem_vars);
//We add the extra filter if needed //We add the extra filter if needed
let right = if let Some(e) = e { let right = if let Some(expr) = expr {
PlanNode::Filter { PlanNode::Filter {
child: Rc::new(right), child: Rc::new(right),
expression: Rc::new(self.build_for_expression(e, variables, graph_name)?), expression: Rc::new(
self.build_for_expression(expr, variables, graph_name)?,
),
} }
} else { } else {
right right
@ -68,20 +100,20 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
possible_problem_vars: Rc::new(possible_problem_vars.into_iter().collect()), possible_problem_vars: Rc::new(possible_problem_vars.into_iter().collect()),
} }
} }
GraphPattern::Filter(e, p) => PlanNode::Filter { GraphPattern::Filter { expr, inner } => PlanNode::Filter {
child: Rc::new(self.build_for_graph_pattern(p, variables, graph_name)?), child: Rc::new(self.build_for_graph_pattern(inner, variables, graph_name)?),
expression: Rc::new(self.build_for_expression(e, variables, graph_name)?), expression: Rc::new(self.build_for_expression(expr, variables, graph_name)?),
}, },
GraphPattern::Union(a, b) => { GraphPattern::Union { left, right } => {
//We flatten the UNIONs //We flatten the UNIONs
let mut stack: Vec<&GraphPattern> = vec![a, b]; let mut stack: Vec<&GraphPattern> = vec![left, right];
let mut children = vec![]; let mut children = vec![];
loop { loop {
match stack.pop() { match stack.pop() {
None => break, None => break,
Some(GraphPattern::Union(a, b)) => { Some(GraphPattern::Union { left, right }) => {
stack.push(a); stack.push(left);
stack.push(b); stack.push(right);
} }
Some(p) => children.push(Rc::new( Some(p) => children.push(Rc::new(
self.build_for_graph_pattern(p, variables, graph_name)?, self.build_for_graph_pattern(p, variables, graph_name)?,
@ -90,44 +122,54 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
} }
PlanNode::Union { children } PlanNode::Union { children }
} }
GraphPattern::Graph(g, p) => { GraphPattern::Graph { graph_name, inner } => {
let graph_name = self.pattern_value_from_named_node_or_variable(g, variables)?; let graph_name =
self.build_for_graph_pattern(p, variables, graph_name)? self.pattern_value_from_named_node_or_variable(graph_name, variables)?;
self.build_for_graph_pattern(inner, variables, graph_name)?
} }
GraphPattern::Extend(p, v, e) => PlanNode::Extend { GraphPattern::Extend { inner, var, expr } => PlanNode::Extend {
child: Rc::new(self.build_for_graph_pattern(p, variables, graph_name)?), child: Rc::new(self.build_for_graph_pattern(inner, variables, graph_name)?),
position: variable_key(variables, v), position: variable_key(variables, var),
expression: Rc::new(self.build_for_expression(e, variables, graph_name)?), expression: Rc::new(self.build_for_expression(expr, variables, graph_name)?),
}, },
GraphPattern::Minus(a, b) => PlanNode::AntiJoin { GraphPattern::Minus { left, right } => PlanNode::AntiJoin {
left: Rc::new(self.build_for_graph_pattern(a, variables, graph_name)?), left: Rc::new(self.build_for_graph_pattern(left, variables, graph_name)?),
right: Rc::new(self.build_for_graph_pattern(b, variables, graph_name)?), right: Rc::new(self.build_for_graph_pattern(right, variables, graph_name)?),
}, },
GraphPattern::Service(n, p, s) => { GraphPattern::Service {
name,
pattern,
silent,
} => {
// Child building should be at the begging in order for `variables` to be filled // 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 child = self.build_for_graph_pattern(pattern, 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(name, variables)?;
PlanNode::Service { PlanNode::Service {
service_name, service_name,
variables: Rc::new(variables.clone()), variables: Rc::new(variables.clone()),
child: Rc::new(child), child: Rc::new(child),
graph_pattern: Rc::new(*p.clone()), graph_pattern: Rc::new(*pattern.clone()),
silent: *s, silent: *silent,
} }
} }
GraphPattern::AggregateJoin(GroupPattern(key, p), aggregates) => { GraphPattern::Group {
let mut inner_variables = key.clone(); inner,
by,
aggregates,
} => {
let mut inner_variables = by.clone();
let inner_graph_name = let inner_graph_name =
self.convert_pattern_value_id(graph_name, variables, &mut inner_variables); self.convert_pattern_value_id(graph_name, variables, &mut inner_variables);
PlanNode::Aggregate { PlanNode::Aggregate {
child: Rc::new(self.build_for_graph_pattern( child: Rc::new(self.build_for_graph_pattern(
p, inner,
&mut inner_variables, &mut inner_variables,
inner_graph_name, inner_graph_name,
)?), )?),
key_mapping: Rc::new( key_mapping: Rc::new(
key.iter() by.iter()
.map(|k| { .map(|k| {
( (
variable_key(&mut inner_variables, k), variable_key(&mut inner_variables, k),
@ -139,7 +181,7 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
aggregates: Rc::new( aggregates: Rc::new(
aggregates aggregates
.iter() .iter()
.map(|(a, v)| { .map(|(v, a)| {
Ok(( Ok((
self.build_for_aggregate(a, &mut inner_variables, graph_name)?, self.build_for_aggregate(a, &mut inner_variables, graph_name)?,
variable_key(variables, v), variable_key(variables, v),
@ -149,11 +191,14 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
), ),
} }
} }
GraphPattern::Data(bs) => PlanNode::StaticBindings { GraphPattern::Table {
tuples: self.encode_bindings(bs, variables)?, variables: table_variables,
rows,
} => PlanNode::StaticBindings {
tuples: self.encode_bindings(table_variables, rows, variables)?,
}, },
GraphPattern::OrderBy(l, o) => { GraphPattern::OrderBy { inner, condition } => {
let by: Result<Vec<_>, EvaluationError> = o let condition: Result<Vec<_>, EvaluationError> = condition
.iter() .iter()
.map(|comp| match comp { .map(|comp| match comp {
OrderComparator::Asc(e) => Ok(Comparator::Asc( OrderComparator::Asc(e) => Ok(Comparator::Asc(
@ -165,22 +210,22 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
}) })
.collect(); .collect();
PlanNode::Sort { PlanNode::Sort {
child: Rc::new(self.build_for_graph_pattern(l, variables, graph_name)?), child: Rc::new(self.build_for_graph_pattern(inner, variables, graph_name)?),
by: by?, by: condition?,
} }
} }
GraphPattern::Project(l, new_variables) => { GraphPattern::Project { inner, projection } => {
let mut inner_variables = new_variables.clone(); let mut inner_variables = projection.clone();
let inner_graph_name = let inner_graph_name =
self.convert_pattern_value_id(graph_name, variables, &mut inner_variables); self.convert_pattern_value_id(graph_name, variables, &mut inner_variables);
PlanNode::Project { PlanNode::Project {
child: Rc::new(self.build_for_graph_pattern( child: Rc::new(self.build_for_graph_pattern(
l, inner,
&mut inner_variables, &mut inner_variables,
inner_graph_name, inner_graph_name,
)?), )?),
mapping: Rc::new( mapping: Rc::new(
new_variables projection
.iter() .iter()
.enumerate() .enumerate()
.map(|(new_variable, variable)| { .map(|(new_variable, variable)| {
@ -190,12 +235,18 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
), ),
} }
} }
GraphPattern::Distinct(l) => PlanNode::HashDeduplicate { GraphPattern::Distinct { inner } => PlanNode::HashDeduplicate {
child: Rc::new(self.build_for_graph_pattern(l, variables, graph_name)?), child: Rc::new(self.build_for_graph_pattern(inner, variables, graph_name)?),
}, },
GraphPattern::Reduced(l) => self.build_for_graph_pattern(l, variables, graph_name)?, GraphPattern::Reduced { inner } => {
GraphPattern::Slice(l, start, length) => { self.build_for_graph_pattern(inner, variables, graph_name)?
let mut plan = self.build_for_graph_pattern(l, variables, graph_name)?; }
GraphPattern::Slice {
inner,
start,
length,
} => {
let mut plan = self.build_for_graph_pattern(inner, variables, graph_name)?;
if *start > 0 { if *start > 0 {
plan = PlanNode::Skip { plan = PlanNode::Skip {
child: Rc::new(plan), child: Rc::new(plan),
@ -215,30 +266,19 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
fn build_for_bgp( fn build_for_bgp(
&mut self, &mut self,
p: &[TripleOrPathPattern], p: &[TriplePattern],
variables: &mut Vec<Variable>, variables: &mut Vec<Variable>,
graph_name: PatternValue<E::StrId>, graph_name: PatternValue<E::StrId>,
) -> Result<PlanNode<E::StrId>, EvaluationError> { ) -> Result<PlanNode<E::StrId>, EvaluationError> {
let mut plan = PlanNode::Init; let mut plan = PlanNode::Init;
for pattern in sort_bgp(p) { for pattern in sort_bgp(p) {
plan = match pattern { plan = PlanNode::QuadPatternJoin {
TripleOrPathPattern::Triple(pattern) => PlanNode::QuadPatternJoin { child: Rc::new(plan),
child: Rc::new(plan), subject: self.pattern_value_from_term_or_variable(&pattern.subject, variables)?,
subject: self predicate: self
.pattern_value_from_term_or_variable(&pattern.subject, variables)?, .pattern_value_from_named_node_or_variable(&pattern.predicate, variables)?,
predicate: self object: self.pattern_value_from_term_or_variable(&pattern.object, variables)?,
.pattern_value_from_named_node_or_variable(&pattern.predicate, variables)?, graph_name,
object: self.pattern_value_from_term_or_variable(&pattern.object, variables)?,
graph_name,
},
TripleOrPathPattern::Path(pattern) => PlanNode::PathPatternJoin {
child: Rc::new(plan),
subject: self
.pattern_value_from_term_or_variable(&pattern.subject, variables)?,
path: Rc::new(self.build_for_path(&pattern.path)?),
object: self.pattern_value_from_term_or_variable(&pattern.object, variables)?,
graph_name,
},
} }
} }
Ok(plan) Ok(plan)
@ -246,37 +286,39 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
fn build_for_path( fn build_for_path(
&mut self, &mut self,
path: &PropertyPath, path: &PropertyPathExpression,
) -> Result<PlanPropertyPath<E::StrId>, EvaluationError> { ) -> Result<PlanPropertyPath<E::StrId>, EvaluationError> {
Ok(match path { Ok(match path {
PropertyPath::PredicatePath(p) => { PropertyPathExpression::NamedNode(p) => {
PlanPropertyPath::PredicatePath(self.build_named_node(p)?) PlanPropertyPath::Path(self.build_named_node(p)?)
} }
PropertyPath::InversePath(p) => { PropertyPathExpression::Reverse(p) => {
PlanPropertyPath::InversePath(Rc::new(self.build_for_path(p)?)) PlanPropertyPath::Reverse(Rc::new(self.build_for_path(p)?))
} }
PropertyPath::AlternativePath(a, b) => PlanPropertyPath::AlternativePath( PropertyPathExpression::Alternative(a, b) => PlanPropertyPath::Alternative(
Rc::new(self.build_for_path(a)?), Rc::new(self.build_for_path(a)?),
Rc::new(self.build_for_path(b)?), Rc::new(self.build_for_path(b)?),
), ),
PropertyPath::SequencePath(a, b) => PlanPropertyPath::SequencePath( PropertyPathExpression::Sequence(a, b) => PlanPropertyPath::Sequence(
Rc::new(self.build_for_path(a)?), Rc::new(self.build_for_path(a)?),
Rc::new(self.build_for_path(b)?), Rc::new(self.build_for_path(b)?),
), ),
PropertyPath::ZeroOrMorePath(p) => { PropertyPathExpression::ZeroOrMore(p) => {
PlanPropertyPath::ZeroOrMorePath(Rc::new(self.build_for_path(p)?)) PlanPropertyPath::ZeroOrMore(Rc::new(self.build_for_path(p)?))
} }
PropertyPath::OneOrMorePath(p) => { PropertyPathExpression::OneOrMore(p) => {
PlanPropertyPath::OneOrMorePath(Rc::new(self.build_for_path(p)?)) PlanPropertyPath::OneOrMore(Rc::new(self.build_for_path(p)?))
} }
PropertyPath::ZeroOrOnePath(p) => { PropertyPathExpression::ZeroOrOne(p) => {
PlanPropertyPath::ZeroOrOnePath(Rc::new(self.build_for_path(p)?)) PlanPropertyPath::ZeroOrOne(Rc::new(self.build_for_path(p)?))
}
PropertyPathExpression::NegatedPropertySet(p) => {
PlanPropertyPath::NegatedPropertySet(Rc::new(
p.iter()
.map(|p| self.build_named_node(p))
.collect::<Result<Vec<_>, _>>()?,
))
} }
PropertyPath::NegatedPropertySet(p) => PlanPropertyPath::NegatedPropertySet(Rc::new(
p.iter()
.map(|p| self.build_named_node(p))
.collect::<Result<Vec<_>, _>>()?,
)),
}) })
} }
@ -302,7 +344,7 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
Box::new(self.build_for_expression(a, variables, graph_name)?), Box::new(self.build_for_expression(a, variables, graph_name)?),
Box::new(self.build_for_expression(b, variables, graph_name)?), Box::new(self.build_for_expression(b, variables, graph_name)?),
), ),
Expression::NotEqual(a, b) => PlanExpression::NotEqual( Expression::SameTerm(a, b) => PlanExpression::SameTerm(
Box::new(self.build_for_expression(a, variables, graph_name)?), Box::new(self.build_for_expression(a, variables, graph_name)?),
Box::new(self.build_for_expression(b, variables, graph_name)?), Box::new(self.build_for_expression(b, variables, graph_name)?),
), ),
@ -310,15 +352,15 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
Box::new(self.build_for_expression(a, variables, graph_name)?), Box::new(self.build_for_expression(a, variables, graph_name)?),
Box::new(self.build_for_expression(b, variables, graph_name)?), Box::new(self.build_for_expression(b, variables, graph_name)?),
), ),
Expression::GreaterOrEq(a, b) => PlanExpression::GreaterOrEq( Expression::GreaterOrEqual(a, b) => PlanExpression::GreaterOrEqual(
Box::new(self.build_for_expression(a, variables, graph_name)?), Box::new(self.build_for_expression(a, variables, graph_name)?),
Box::new(self.build_for_expression(b, variables, graph_name)?), Box::new(self.build_for_expression(b, variables, graph_name)?),
), ),
Expression::Lower(a, b) => PlanExpression::Lower( Expression::Less(a, b) => PlanExpression::Less(
Box::new(self.build_for_expression(a, variables, graph_name)?), Box::new(self.build_for_expression(a, variables, graph_name)?),
Box::new(self.build_for_expression(b, variables, graph_name)?), Box::new(self.build_for_expression(b, variables, graph_name)?),
), ),
Expression::LowerOrEq(a, b) => PlanExpression::LowerOrEq( Expression::LessOrEqual(a, b) => PlanExpression::LessOrEqual(
Box::new(self.build_for_expression(a, variables, graph_name)?), Box::new(self.build_for_expression(a, variables, graph_name)?),
Box::new(self.build_for_expression(b, variables, graph_name)?), Box::new(self.build_for_expression(b, variables, graph_name)?),
), ),
@ -326,23 +368,19 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
Box::new(self.build_for_expression(e, variables, graph_name)?), Box::new(self.build_for_expression(e, variables, graph_name)?),
self.expression_list(l, variables, graph_name)?, self.expression_list(l, variables, graph_name)?,
), ),
Expression::NotIn(e, l) => PlanExpression::UnaryNot(Box::new(PlanExpression::In(
Box::new(self.build_for_expression(e, variables, graph_name)?),
self.expression_list(l, variables, graph_name)?,
))),
Expression::Add(a, b) => PlanExpression::Add( Expression::Add(a, b) => PlanExpression::Add(
Box::new(self.build_for_expression(a, variables, graph_name)?), Box::new(self.build_for_expression(a, variables, graph_name)?),
Box::new(self.build_for_expression(b, variables, graph_name)?), Box::new(self.build_for_expression(b, variables, graph_name)?),
), ),
Expression::Sub(a, b) => PlanExpression::Sub( Expression::Subtract(a, b) => PlanExpression::Subtract(
Box::new(self.build_for_expression(a, variables, graph_name)?), Box::new(self.build_for_expression(a, variables, graph_name)?),
Box::new(self.build_for_expression(b, variables, graph_name)?), Box::new(self.build_for_expression(b, variables, graph_name)?),
), ),
Expression::Mul(a, b) => PlanExpression::Mul( Expression::Multiply(a, b) => PlanExpression::Multiply(
Box::new(self.build_for_expression(a, variables, graph_name)?), Box::new(self.build_for_expression(a, variables, graph_name)?),
Box::new(self.build_for_expression(b, variables, graph_name)?), Box::new(self.build_for_expression(b, variables, graph_name)?),
), ),
Expression::Div(a, b) => PlanExpression::Div( Expression::Divide(a, b) => PlanExpression::Divide(
Box::new(self.build_for_expression(a, variables, graph_name)?), Box::new(self.build_for_expression(a, variables, graph_name)?),
Box::new(self.build_for_expression(b, variables, graph_name)?), Box::new(self.build_for_expression(b, variables, graph_name)?),
), ),
@ -352,7 +390,7 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
Expression::UnaryMinus(e) => PlanExpression::UnaryMinus(Box::new( Expression::UnaryMinus(e) => PlanExpression::UnaryMinus(Box::new(
self.build_for_expression(e, variables, graph_name)?, self.build_for_expression(e, variables, graph_name)?,
)), )),
Expression::UnaryNot(e) => PlanExpression::UnaryNot(Box::new( Expression::Not(e) => PlanExpression::Not(Box::new(
self.build_for_expression(e, variables, graph_name)?, self.build_for_expression(e, variables, graph_name)?,
)), )),
Expression::FunctionCall(function, parameters) => match function { Expression::FunctionCall(function, parameters) => match function {
@ -533,14 +571,6 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
variables, variables,
graph_name, graph_name,
)?)), )?)),
Function::Coalesce => PlanExpression::Coalesce(
self.expression_list(parameters, variables, graph_name)?,
),
Function::If => PlanExpression::If(
Box::new(self.build_for_expression(&parameters[0], variables, graph_name)?),
Box::new(self.build_for_expression(&parameters[1], variables, graph_name)?),
Box::new(self.build_for_expression(&parameters[2], variables, graph_name)?),
),
Function::StrLang => PlanExpression::StrLang( Function::StrLang => PlanExpression::StrLang(
Box::new(self.build_for_expression(&parameters[0], variables, graph_name)?), Box::new(self.build_for_expression(&parameters[0], variables, graph_name)?),
Box::new(self.build_for_expression(&parameters[1], variables, graph_name)?), Box::new(self.build_for_expression(&parameters[1], variables, graph_name)?),
@ -549,10 +579,6 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
Box::new(self.build_for_expression(&parameters[0], variables, graph_name)?), Box::new(self.build_for_expression(&parameters[0], variables, graph_name)?),
Box::new(self.build_for_expression(&parameters[1], variables, graph_name)?), Box::new(self.build_for_expression(&parameters[1], variables, graph_name)?),
), ),
Function::SameTerm => PlanExpression::SameTerm(
Box::new(self.build_for_expression(&parameters[0], variables, graph_name)?),
Box::new(self.build_for_expression(&parameters[1], variables, graph_name)?),
),
Function::IsIRI => PlanExpression::IsIRI(Box::new(self.build_for_expression( Function::IsIRI => PlanExpression::IsIRI(Box::new(self.build_for_expression(
&parameters[0], &parameters[0],
variables, variables,
@ -685,9 +711,17 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
} }
}, },
Expression::Bound(v) => PlanExpression::Bound(variable_key(variables, v)), Expression::Bound(v) => PlanExpression::Bound(variable_key(variables, v)),
Expression::If(a, b, c) => PlanExpression::If(
Box::new(self.build_for_expression(a, variables, graph_name)?),
Box::new(self.build_for_expression(b, variables, graph_name)?),
Box::new(self.build_for_expression(c, variables, graph_name)?),
),
Expression::Exists(n) => PlanExpression::Exists(Rc::new( Expression::Exists(n) => PlanExpression::Exists(Rc::new(
self.build_for_graph_pattern(n, variables, graph_name)?, self.build_for_graph_pattern(n, variables, graph_name)?,
)), )),
Expression::Coalesce(parameters) => {
PlanExpression::Coalesce(self.expression_list(parameters, variables, graph_name)?)
}
}) })
} }
@ -761,19 +795,18 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
fn encode_bindings( fn encode_bindings(
&mut self, &mut self,
bindings: &StaticBindings, table_variables: &[Variable],
rows: &[Vec<Option<Term>>],
variables: &mut Vec<Variable>, variables: &mut Vec<Variable>,
) -> Result<Vec<EncodedTuple<E::StrId>>, EvaluationError> { ) -> Result<Vec<EncodedTuple<E::StrId>>, EvaluationError> {
let bindings_variables_keys = bindings let bindings_variables_keys = table_variables
.variables()
.iter() .iter()
.map(|v| variable_key(variables, v)) .map(|v| variable_key(variables, v))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
bindings rows.iter()
.values_iter() .map(move |row| {
.map(move |values| {
let mut result = EncodedTuple::with_capacity(variables.len()); let mut result = EncodedTuple::with_capacity(variables.len());
for (key, value) in values.iter().enumerate() { for (key, value) in row.iter().enumerate() {
if let Some(term) = value { if let Some(term) = value {
result.set(bindings_variables_keys[key], self.build_term(term)?); result.set(bindings_variables_keys[key], self.build_term(term)?);
} }
@ -785,49 +818,53 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
fn build_for_aggregate( fn build_for_aggregate(
&mut self, &mut self,
aggregate: &Aggregation, aggregate: &SetFunction,
variables: &mut Vec<Variable>, variables: &mut Vec<Variable>,
graph_name: PatternValue<E::StrId>, graph_name: PatternValue<E::StrId>,
) -> Result<PlanAggregation<E::StrId>, EvaluationError> { ) -> Result<PlanAggregation<E::StrId>, EvaluationError> {
Ok(match aggregate { Ok(match aggregate {
Aggregation::Count(e, distinct) => PlanAggregation { SetFunction::Count { expr, distinct } => PlanAggregation {
function: PlanAggregationFunction::Count, function: PlanAggregationFunction::Count,
parameter: match e { parameter: match expr {
Some(e) => Some(self.build_for_expression(e, variables, graph_name)?), Some(expr) => Some(self.build_for_expression(expr, variables, graph_name)?),
None => None, None => None,
}, },
distinct: *distinct, distinct: *distinct,
}, },
Aggregation::Sum(e, distinct) => PlanAggregation { SetFunction::Sum { expr, distinct } => PlanAggregation {
function: PlanAggregationFunction::Sum, function: PlanAggregationFunction::Sum,
parameter: Some(self.build_for_expression(e, variables, graph_name)?), parameter: Some(self.build_for_expression(expr, variables, graph_name)?),
distinct: *distinct, distinct: *distinct,
}, },
Aggregation::Min(e, distinct) => PlanAggregation { SetFunction::Min { expr, distinct } => PlanAggregation {
function: PlanAggregationFunction::Min, function: PlanAggregationFunction::Min,
parameter: Some(self.build_for_expression(e, variables, graph_name)?), parameter: Some(self.build_for_expression(expr, variables, graph_name)?),
distinct: *distinct, distinct: *distinct,
}, },
Aggregation::Max(e, distinct) => PlanAggregation { SetFunction::Max { expr, distinct } => PlanAggregation {
function: PlanAggregationFunction::Max, function: PlanAggregationFunction::Max,
parameter: Some(self.build_for_expression(e, variables, graph_name)?), parameter: Some(self.build_for_expression(expr, variables, graph_name)?),
distinct: *distinct, distinct: *distinct,
}, },
Aggregation::Avg(e, distinct) => PlanAggregation { SetFunction::Avg { expr, distinct } => PlanAggregation {
function: PlanAggregationFunction::Avg, function: PlanAggregationFunction::Avg,
parameter: Some(self.build_for_expression(e, variables, graph_name)?), parameter: Some(self.build_for_expression(expr, variables, graph_name)?),
distinct: *distinct, distinct: *distinct,
}, },
Aggregation::Sample(e, distinct) => PlanAggregation { SetFunction::Sample { expr, distinct } => PlanAggregation {
function: PlanAggregationFunction::Sample, function: PlanAggregationFunction::Sample,
parameter: Some(self.build_for_expression(e, variables, graph_name)?), parameter: Some(self.build_for_expression(expr, variables, graph_name)?),
distinct: *distinct, distinct: *distinct,
}, },
Aggregation::GroupConcat(e, distinct, separator) => PlanAggregation { SetFunction::GroupConcat {
expr,
distinct,
separator,
} => PlanAggregation {
function: PlanAggregationFunction::GroupConcat { function: PlanAggregationFunction::GroupConcat {
separator: Rc::new(separator.clone().unwrap_or_else(|| " ".to_string())), separator: Rc::new(separator.clone().unwrap_or_else(|| " ".to_string())),
}, },
parameter: Some(self.build_for_expression(e, variables, graph_name)?), parameter: Some(self.build_for_expression(expr, variables, graph_name)?),
distinct: *distinct, distinct: *distinct,
}, },
}) })
@ -1041,7 +1078,7 @@ fn slice_key<T: Eq>(slice: &[T], element: &T) -> Option<usize> {
None None
} }
fn sort_bgp(p: &[TripleOrPathPattern]) -> Vec<&TripleOrPathPattern> { fn sort_bgp(p: &[TriplePattern]) -> Vec<&TriplePattern> {
let mut assigned_variables = HashSet::default(); let mut assigned_variables = HashSet::default();
let mut assigned_blank_nodes = HashSet::default(); let mut assigned_blank_nodes = HashSet::default();
let mut new_p: Vec<_> = p.iter().collect(); let mut new_p: Vec<_> = p.iter().collect();
@ -1059,38 +1096,34 @@ fn sort_bgp(p: &[TripleOrPathPattern]) -> Vec<&TripleOrPathPattern> {
} }
fn count_pattern_binds( fn count_pattern_binds(
pattern: &TripleOrPathPattern, pattern: &TriplePattern,
assigned_variables: &HashSet<&Variable>, assigned_variables: &HashSet<&Variable>,
assigned_blank_nodes: &HashSet<&BlankNode>, assigned_blank_nodes: &HashSet<&BlankNode>,
) -> u8 { ) -> u8 {
let mut count = 12; let mut count = 12;
if let TermOrVariable::Variable(v) = pattern.subject() { if let TermOrVariable::Variable(v) = &pattern.subject {
if !assigned_variables.contains(v) { if !assigned_variables.contains(v) {
count -= 4; count -= 4;
} }
} else if let TermOrVariable::Term(Term::BlankNode(bnode)) = pattern.subject() { } else if let TermOrVariable::Term(Term::BlankNode(bnode)) = &pattern.subject {
if !assigned_blank_nodes.contains(bnode) { if !assigned_blank_nodes.contains(bnode) {
count -= 4; count -= 4;
} }
} else { } else {
count -= 1; count -= 1;
} }
if let TripleOrPathPattern::Triple(t) = pattern { if let NamedNodeOrVariable::Variable(v) = &pattern.predicate {
if let NamedNodeOrVariable::Variable(v) = &t.predicate { if !assigned_variables.contains(v) {
if !assigned_variables.contains(v) { count -= 4;
count -= 4;
}
} else {
count -= 1;
} }
} else { } else {
count -= 3; count -= 1;
} }
if let TermOrVariable::Variable(v) = pattern.object() { if let TermOrVariable::Variable(v) = &pattern.object {
if !assigned_variables.contains(v) { if !assigned_variables.contains(v) {
count -= 4; count -= 4;
} }
} else if let TermOrVariable::Term(Term::BlankNode(bnode)) = pattern.object() { } else if let TermOrVariable::Term(Term::BlankNode(bnode)) = &pattern.object {
if !assigned_blank_nodes.contains(bnode) { if !assigned_blank_nodes.contains(bnode) {
count -= 4; count -= 4;
} }
@ -1101,23 +1134,21 @@ fn count_pattern_binds(
} }
fn add_pattern_variables<'a>( fn add_pattern_variables<'a>(
pattern: &'a TripleOrPathPattern, pattern: &'a TriplePattern,
variables: &mut HashSet<&'a Variable>, variables: &mut HashSet<&'a Variable>,
blank_nodes: &mut HashSet<&'a BlankNode>, blank_nodes: &mut HashSet<&'a BlankNode>,
) { ) {
if let TermOrVariable::Variable(v) = pattern.subject() { if let TermOrVariable::Variable(v) = &pattern.subject {
variables.insert(v); variables.insert(v);
} else if let TermOrVariable::Term(Term::BlankNode(bnode)) = pattern.subject() { } else if let TermOrVariable::Term(Term::BlankNode(bnode)) = &pattern.subject {
blank_nodes.insert(bnode); blank_nodes.insert(bnode);
} }
if let TripleOrPathPattern::Triple(t) = pattern { if let NamedNodeOrVariable::Variable(v) = &pattern.predicate {
if let NamedNodeOrVariable::Variable(v) = &t.predicate { variables.insert(v);
variables.insert(v);
}
} }
if let TermOrVariable::Variable(v) = pattern.object() { if let TermOrVariable::Variable(v) = &pattern.object {
variables.insert(v); variables.insert(v);
} else if let TermOrVariable::Term(Term::BlankNode(bnode)) = pattern.object() { } else if let TermOrVariable::Term(Term::BlankNode(bnode)) = &pattern.object {
blank_nodes.insert(bnode); blank_nodes.insert(bnode);
} }
} }

@ -69,8 +69,8 @@ where
delete, delete,
insert, insert,
using, using,
algebra, pattern,
} => self.eval_delete_insert(delete, insert, using, algebra), } => self.eval_delete_insert(delete, insert, using, pattern),
GraphUpdateOperation::Load { silent, from, to } => { GraphUpdateOperation::Load { silent, from, to } => {
if let Err(error) = self.eval_load(from, to) { if let Err(error) = self.eval_load(from, to) {
if *silent { if *silent {

@ -238,7 +238,7 @@ impl MemoryStore {
evaluate_update( evaluate_update(
self.clone(), self.clone(),
&mut &*self, &mut &*self,
&update.try_into().map_err(|e| e.into())?, update.try_into().map_err(|e| e.into())?,
) )
} }

@ -220,7 +220,7 @@ impl RocksDbStore {
evaluate_update( evaluate_update(
self.clone(), self.clone(),
&mut writer, &mut writer,
&update.try_into().map_err(|e| e.into())?, update.try_into().map_err(|e| e.into())?,
)?; )?;
Ok(writer.apply()?) Ok(writer.apply()?)
} }

@ -211,7 +211,7 @@ impl SledStore {
evaluate_update( evaluate_update(
self.clone(), self.clone(),
&mut &*self, &mut &*self,
&update.try_into().map_err(|e| e.into())?, update.try_into().map_err(|e| e.into())?,
) )
} }

Loading…
Cancel
Save