diff --git a/lib/src/sparql/plan_builder.rs b/lib/src/sparql/plan_builder.rs index e52811e4..df43487f 100644 --- a/lib/src/sparql/plan_builder.rs +++ b/lib/src/sparql/plan_builder.rs @@ -69,20 +69,6 @@ impl<'a> PlanBuilder<'a> { object: self.pattern_value_from_term_or_variable(object, variables), graph_name: graph_name.clone(), }, - GraphPattern::Sequence(elements) => elements - .iter() - .map(|e| self.build_for_graph_pattern(e, variables, graph_name)) - .reduce(|left, right| { - Ok(PlanNode::ForLoopJoin { - left: Rc::new(left?), - right: Rc::new(right?), - }) - }) - .unwrap_or_else(|| { - Ok(PlanNode::StaticBindings { - tuples: vec![EncodedTuple::with_capacity(variables.len())], - }) - })?, GraphPattern::Join { left, right } => PlanNode::HashJoin { left: Rc::new(self.build_for_graph_pattern(left, variables, graph_name)?), right: Rc::new(self.build_for_graph_pattern(right, variables, graph_name)?), diff --git a/spargebra/src/algebra.rs b/spargebra/src/algebra.rs index 02e7bc8a..16a47b9d 100644 --- a/spargebra/src/algebra.rs +++ b/spargebra/src/algebra.rs @@ -522,9 +522,6 @@ pub enum GraphPattern { path: PropertyPathExpression, object: TermPattern, }, - /// A set of SPARQL patterns that can be evaluated sequentially - /// It is a safe case of [Join](https://www.w3.org/TR/sparql11-query/#defn_algJoin) - Sequence(Vec), /// [Join](https://www.w3.org/TR/sparql11-query/#defn_algJoin) Join { left: Box, right: Box }, /// [LeftJoin](https://www.w3.org/TR/sparql11-query/#defn_algLeftJoin) @@ -613,14 +610,6 @@ impl GraphPattern { object.fmt_sse(f)?; write!(f, ")") } - Self::Sequence(elements) => { - write!(f, "(sequence")?; - for e in elements { - write!(f, " ")?; - e.fmt_sse(f)?; - } - write!(f, ")") - } Self::Join { left, right } => { write!(f, "(join ")?; left.fmt_sse(f)?; @@ -815,12 +804,6 @@ impl fmt::Display for GraphPattern { path, object, } => write!(f, "{} {} {} .", subject, path, object), - Self::Sequence(elements) => { - for e in elements { - write!(f, "{} ", e)?; - } - Ok(()) - } Self::Join { left, right } => { if matches!( right.as_ref(), @@ -963,11 +946,6 @@ impl GraphPattern { lookup_triple_pattern_variables(o, callback) } } - Self::Sequence(elements) => { - for e in elements { - e.lookup_in_scope_variables(callback); - } - } Self::Join { left, right } | Self::LeftJoin { left, right, .. } | Self::Union { left, right } => { diff --git a/spargebra/src/parser.rs b/spargebra/src/parser.rs index e0f5e921..d3c03567 100644 --- a/spargebra/src/parser.rs +++ b/spargebra/src/parser.rs @@ -277,7 +277,10 @@ fn build_bgp(patterns: Vec) -> GraphPattern { if !bgp.is_empty() { elements.push(GraphPattern::Bgp { patterns: bgp }); } - new_sequence(elements) + elements + .into_iter() + .reduce(new_join) + .unwrap_or_else(GraphPattern::default) } enum TripleOrPathPattern { @@ -368,38 +371,15 @@ fn new_join(l: GraphPattern, r: GraphPattern) -> GraphPattern { } } - // Some optimizations - // TODO: move to a specific optimizer pass match (l, r) { (GraphPattern::Bgp { patterns: mut pl }, GraphPattern::Bgp { patterns: pr }) => { pl.extend(pr); GraphPattern::Bgp { patterns: pl } } - (GraphPattern::Sequence(mut e1), GraphPattern::Sequence(e2)) => { - e1.extend_from_slice(&e2); - GraphPattern::Sequence(e1) - } - (GraphPattern::Sequence(mut e), r) - if matches!(r, GraphPattern::Bgp { .. } | GraphPattern::Path { .. }) => - { - e.push(r); - GraphPattern::Sequence(e) - } - (l, GraphPattern::Sequence(mut e)) - if matches!(l, GraphPattern::Bgp { .. } | GraphPattern::Path { .. }) => + (GraphPattern::Bgp { patterns }, other) | (other, GraphPattern::Bgp { patterns }) + if patterns.is_empty() => { - e.insert(0, l); - GraphPattern::Sequence(e) - } - ( - GraphPattern::Graph { name: g1, inner: l }, - GraphPattern::Graph { name: g2, inner: r }, - ) if g1 == g2 => { - // We merge identical graphs - GraphPattern::Graph { - name: g1, - inner: Box::new(new_join(*l, *r)), - } + other } (l, r) => GraphPattern::Join { left: Box::new(l), @@ -408,14 +388,6 @@ fn new_join(l: GraphPattern, r: GraphPattern) -> GraphPattern { } } -fn new_sequence(elements: Vec) -> GraphPattern { - match elements.len() { - 0 => GraphPattern::default(), - 1 => elements.into_iter().next().unwrap(), - _ => GraphPattern::Sequence(elements), - } -} - fn not_empty_fold( iter: impl Iterator, combine: impl Fn(T, T) -> T, @@ -1219,14 +1191,14 @@ parser! { //[40] rule DeleteWhere() -> Vec = i("DELETE") _ i("WHERE") _ d:QuadPattern() {? - let pattern = new_sequence(d.iter().map(|q| { + let pattern = d.iter().map(|q| { let bgp = GraphPattern::Bgp { patterns: vec![TriplePattern::new(q.subject.clone(), q.predicate.clone(), q.object.clone())] }; match &q.graph_name { GraphNamePattern::NamedNode(graph_name) => GraphPattern::Graph { name: graph_name.clone().into(), inner: Box::new(bgp) }, GraphNamePattern::DefaultGraph => bgp, GraphNamePattern::Variable(graph_name) => GraphPattern::Graph { name: graph_name.clone().into(), inner: Box::new(bgp) }, } - }).collect()); + }).reduce(new_join).unwrap_or_else(GraphPattern::default); let delete = d.into_iter().map(GroundQuadPattern::try_from).collect::,_>>().map_err(|_| "Blank nodes are not allowed in DELETE WHERE")?; Ok(vec![GraphUpdateOperation::DeleteInsert { delete,