Rework SPARQL algebra and makes it public

pull/71/head
Tpt 4 years ago
parent 40a08ac623
commit 34f0efbb39
  1. 1466
      lib/src/sparql/algebra.rs
  2. 96
      lib/src/sparql/eval.rs
  3. 61
      lib/src/sparql/mod.rs
  4. 467
      lib/src/sparql/parser.rs
  5. 44
      lib/src/sparql/plan.rs
  6. 323
      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::Triple;
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::model::*;
use crate::sparql::plan::*;
@ -134,12 +134,8 @@ where
service_name,
graph_pattern,
..
} => match self.evaluate_service(
service_name,
graph_pattern.clone(),
variables.clone(),
&from,
) {
} => {
match self.evaluate_service(service_name, graph_pattern, variables.clone(), &from) {
Ok(result) => Box::new(result.flat_map(move |binding| {
binding
.map(|binding| binding.combine_with(&from))
@ -152,7 +148,8 @@ where
Box::new(once(Err(e)))
}
}
},
}
}
PlanNode::QuadPatternJoin {
child,
subject,
@ -516,7 +513,7 @@ where
fn evaluate_service(
&self,
service_name: &PatternValue<S::StrId>,
graph_pattern: Rc<GraphPattern>,
graph_pattern: &GraphPattern,
variables: Rc<Vec<Variable>>,
from: &EncodedTuple<S::StrId>,
) -> Result<EncodedTuplesIterator<S::StrId>, EvaluationError> {
@ -525,11 +522,11 @@ where
get_pattern_value(service_name, from)
.ok_or_else(|| EvaluationError::msg("The SERVICE name is not bound"))?,
)?,
Query(QueryVariants::Select {
Query::Select {
dataset: QueryDataset::default(),
algebra: graph_pattern,
base_iri: self.base_iri.clone(),
}),
pattern: graph_pattern.clone(),
base_iri: self.base_iri.as_ref().map(|iri| iri.as_ref().clone()),
},
)? {
Ok(self.encode_bindings(variables, iter))
} else {
@ -589,13 +586,13 @@ where
graph_name: EncodedTerm<S::StrId>,
) -> Box<dyn Iterator<Item = Result<EncodedTerm<S::StrId>, EvaluationError>>> {
match path {
PlanPropertyPath::PredicatePath(p) => Box::new(
PlanPropertyPath::Path(p) => Box::new(
self.dataset
.encoded_quads_for_pattern(Some(start), Some(*p), None, Some(graph_name))
.map(|t| Ok(t?.object)),
),
PlanPropertyPath::InversePath(p) => self.eval_path_to(p, start, graph_name),
PlanPropertyPath::SequencePath(a, b) => {
PlanPropertyPath::Reverse(p) => self.eval_path_to(p, start, graph_name),
PlanPropertyPath::Sequence(a, b) => {
let eval = self.clone();
let b = b.clone();
Box::new(
@ -603,18 +600,18 @@ where
.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)
.chain(self.eval_path_from(b, start, graph_name)),
),
PlanPropertyPath::ZeroOrMorePath(p) => {
PlanPropertyPath::ZeroOrMore(p) => {
let eval = self.clone();
let p = p.clone();
Box::new(transitive_closure(Some(Ok(start)), move |e| {
eval.eval_path_from(&p, e, graph_name)
}))
}
PlanPropertyPath::OneOrMorePath(p) => {
PlanPropertyPath::OneOrMore(p) => {
let eval = self.clone();
let p = p.clone();
Box::new(transitive_closure(
@ -622,7 +619,7 @@ where
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)),
)),
PlanPropertyPath::NegatedPropertySet(ps) => {
@ -652,13 +649,13 @@ where
graph_name: EncodedTerm<S::StrId>,
) -> Box<dyn Iterator<Item = Result<EncodedTerm<S::StrId>, EvaluationError>>> {
match path {
PlanPropertyPath::PredicatePath(p) => Box::new(
PlanPropertyPath::Path(p) => Box::new(
self.dataset
.encoded_quads_for_pattern(None, Some(*p), Some(end), Some(graph_name))
.map(|t| Ok(t?.subject)),
),
PlanPropertyPath::InversePath(p) => self.eval_path_from(p, end, graph_name),
PlanPropertyPath::SequencePath(a, b) => {
PlanPropertyPath::Reverse(p) => self.eval_path_from(p, end, graph_name),
PlanPropertyPath::Sequence(a, b) => {
let eval = self.clone();
let a = a.clone();
Box::new(
@ -666,18 +663,18 @@ where
.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)
.chain(self.eval_path_to(b, end, graph_name)),
),
PlanPropertyPath::ZeroOrMorePath(p) => {
PlanPropertyPath::ZeroOrMore(p) => {
let eval = self.clone();
let p = p.clone();
Box::new(transitive_closure(Some(Ok(end)), move |e| {
eval.eval_path_to(&p, e, graph_name)
}))
}
PlanPropertyPath::OneOrMorePath(p) => {
PlanPropertyPath::OneOrMore(p) => {
let eval = self.clone();
let p = p.clone();
Box::new(transitive_closure(
@ -685,7 +682,7 @@ where
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)),
)),
PlanPropertyPath::NegatedPropertySet(ps) => {
@ -718,16 +715,16 @@ where
>,
> {
match path {
PlanPropertyPath::PredicatePath(p) => Box::new(
PlanPropertyPath::Path(p) => Box::new(
self.dataset
.encoded_quads_for_pattern(None, Some(*p), None, Some(graph_name))
.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)
.map(|t| t.map(|(s, o)| (o, s))),
),
PlanPropertyPath::SequencePath(a, b) => {
PlanPropertyPath::Sequence(a, b) => {
let eval = self.clone();
let b = b.clone();
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)
.chain(self.eval_open_path(b, graph_name)),
),
PlanPropertyPath::ZeroOrMorePath(p) => {
PlanPropertyPath::ZeroOrMore(p) => {
let eval = self.clone();
let p = p.clone();
Box::new(transitive_closure(
@ -753,7 +750,7 @@ where
},
))
}
PlanPropertyPath::OneOrMorePath(p) => {
PlanPropertyPath::OneOrMore(p) => {
let eval = self.clone();
let p = p.clone();
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)
.chain(self.eval_open_path(p, graph_name)),
)),
@ -845,11 +842,6 @@ where
let b = self.eval_expression(b, tuple)?;
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(
(self.partial_cmp_literals(
self.eval_expression(a, tuple)?,
@ -857,7 +849,7 @@ where
)? == Ordering::Greater)
.into(),
),
PlanExpression::GreaterOrEq(a, b) => Some(
PlanExpression::GreaterOrEqual(a, b) => Some(
match self.partial_cmp_literals(
self.eval_expression(a, tuple)?,
self.eval_expression(b, tuple)?,
@ -867,14 +859,14 @@ where
}
.into(),
),
PlanExpression::Lower(a, b) => Some(
PlanExpression::Less(a, b) => Some(
(self.partial_cmp_literals(
self.eval_expression(a, tuple)?,
self.eval_expression(b, tuple)?,
)? == Ordering::Less)
.into(),
),
PlanExpression::LowerOrEq(a, b) => Some(
PlanExpression::LessOrEqual(a, b) => Some(
match self.partial_cmp_literals(
self.eval_expression(a, tuple)?,
self.eval_expression(b, tuple)?,
@ -938,7 +930,8 @@ where
}
_ => None,
},
PlanExpression::Sub(a, b) => Some(match self.parse_numeric_operands(a, b, tuple)? {
PlanExpression::Subtract(a, b) => {
Some(match self.parse_numeric_operands(a, b, tuple)? {
NumericBinaryOperands::Float(v1, v2) => (v1 - v2).into(),
NumericBinaryOperands::Double(v1, v2) => (v1 - v2).into(),
NumericBinaryOperands::Integer(v1, v2) => v1.checked_sub(v2)?.into(),
@ -958,26 +951,31 @@ where
NumericBinaryOperands::DateTimeDayTimeDuration(v1, v2) => {
v1.checked_sub_day_time_duration(v2)?.into()
}
NumericBinaryOperands::DateDuration(v1, v2) => v1.checked_sub_duration(v2)?.into(),
NumericBinaryOperands::DateDuration(v1, v2) => {
v1.checked_sub_duration(v2)?.into()
}
NumericBinaryOperands::DateYearMonthDuration(v1, v2) => {
v1.checked_sub_year_month_duration(v2)?.into()
}
NumericBinaryOperands::DateDayTimeDuration(v1, v2) => {
v1.checked_sub_day_time_duration(v2)?.into()
}
NumericBinaryOperands::TimeDuration(v1, v2) => v1.checked_sub_duration(v2)?.into(),
NumericBinaryOperands::TimeDuration(v1, v2) => {
v1.checked_sub_duration(v2)?.into()
}
NumericBinaryOperands::TimeDayTimeDuration(v1, v2) => {
v1.checked_sub_day_time_duration(v2)?.into()
}
}),
PlanExpression::Mul(a, b) => match self.parse_numeric_operands(a, b, tuple)? {
})
}
PlanExpression::Multiply(a, b) => match self.parse_numeric_operands(a, b, tuple)? {
NumericBinaryOperands::Float(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::Decimal(v1, v2) => Some(v1.checked_mul(v2)?.into()),
_ => 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::Double(v1, v2) => Some((v1 / v2).into()),
NumericBinaryOperands::Integer(v1, v2) => {
@ -1006,7 +1004,7 @@ where
EncodedTerm::DayTimeDurationLiteral(value) => Some((-value).into()),
_ => None,
},
PlanExpression::UnaryNot(e) => self
PlanExpression::Not(e) => self
.to_bool(self.eval_expression(e, tuple)?)
.map(|v| (!v).into()),
PlanExpression::Str(e) => {

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

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

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

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

@ -238,7 +238,7 @@ impl MemoryStore {
evaluate_update(
self.clone(),
&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(
self.clone(),
&mut writer,
&update.try_into().map_err(|e| e.into())?,
update.try_into().map_err(|e| e.into())?,
)?;
Ok(writer.apply()?)
}

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

Loading…
Cancel
Save