diff --git a/lib/src/sparql/plan_builder.rs b/lib/src/sparql/plan_builder.rs index 27e2a5d9..1bd1404e 100644 --- a/lib/src/sparql/plan_builder.rs +++ b/lib/src/sparql/plan_builder.rs @@ -43,14 +43,20 @@ impl<'a> PlanBuilder<'a> { graph_name: &PatternValue, ) -> Result { Ok(match pattern { - GraphPattern::Bgp(_) | GraphPattern::Path { .. } | GraphPattern::Sequence { .. } => { + GraphPattern::Bgp { .. } + | GraphPattern::Path { .. } + | GraphPattern::Sequence { .. } => { self.build_sequence(PlanNode::Init, pattern, variables, graph_name)? } GraphPattern::Join { left, right } => 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 } => { + GraphPattern::LeftJoin { + left, + right, + expression, + } => { let left = self.build_for_graph_pattern(left, variables, graph_name)?; let right = self.build_for_graph_pattern(right, variables, graph_name)?; @@ -58,7 +64,7 @@ impl<'a> PlanBuilder<'a> { self.add_left_join_problematic_variables(&right, &mut possible_problem_vars); //We add the extra filter if needed - let right = if let Some(expr) = expr { + let right = if let Some(expr) = expression { PlanNode::Filter { child: Rc::new(right), expression: Rc::new( @@ -97,15 +103,18 @@ impl<'a> PlanBuilder<'a> { } PlanNode::Union { children } } - GraphPattern::Graph { graph_name, inner } => { - let graph_name = - self.pattern_value_from_named_node_or_variable(graph_name, variables); + GraphPattern::Graph { name, inner } => { + let graph_name = self.pattern_value_from_named_node_or_variable(name, variables); self.build_for_graph_pattern(inner, variables, &graph_name)? } - GraphPattern::Extend { inner, var, expr } => PlanNode::Extend { + GraphPattern::Extend { + inner, + variable, + expression, + } => 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)?), + position: variable_key(variables, variable), + expression: Rc::new(self.build_for_expression(expression, variables, graph_name)?), }, GraphPattern::Minus { left, right } => PlanNode::AntiJoin { left: Rc::new(self.build_for_graph_pattern(left, variables, graph_name)?), @@ -113,11 +122,11 @@ impl<'a> PlanBuilder<'a> { }, GraphPattern::Service { name, - pattern, + inner, silent, } => { // Child building should be at the begging in order for `variables` to be filled - let child = self.build_for_graph_pattern(pattern, variables, graph_name)?; + let child = self.build_for_graph_pattern(inner, variables, graph_name)?; let service_name = self.pattern_value_from_named_node_or_variable(name, variables); PlanNode::Service { service_name, @@ -128,13 +137,13 @@ impl<'a> PlanBuilder<'a> { .collect(), ), child: Rc::new(child), - graph_pattern: Rc::new(*pattern.clone()), + graph_pattern: Rc::new(inner.as_ref().clone()), silent: *silent, } } GraphPattern::Group { inner, - by, + variables: by, aggregates, } => { let mut inner_variables = by.clone(); @@ -170,20 +179,20 @@ impl<'a> PlanBuilder<'a> { ), } } - GraphPattern::Table { + GraphPattern::Values { variables: table_variables, - rows, + bindings, } => PlanNode::StaticBindings { - tuples: self.encode_bindings(table_variables, rows, variables), + tuples: self.encode_bindings(table_variables, bindings, variables), }, - GraphPattern::OrderBy { inner, condition } => { - let condition: Result, EvaluationError> = condition + GraphPattern::OrderBy { inner, expression } => { + let condition: Result, EvaluationError> = expression .iter() .map(|comp| match comp { - OrderComparator::Asc(e) => Ok(Comparator::Asc( + OrderExpression::Asc(e) => Ok(Comparator::Asc( self.build_for_expression(e, variables, graph_name)?, )), - OrderComparator::Desc(e) => Ok(Comparator::Desc( + OrderExpression::Desc(e) => Ok(Comparator::Desc( self.build_for_expression(e, variables, graph_name)?, )), }) @@ -193,7 +202,10 @@ impl<'a> PlanBuilder<'a> { by: condition?, } } - GraphPattern::Project { inner, projection } => { + GraphPattern::Project { + inner, + variables: projection, + } => { let mut inner_variables = projection.clone(); let inner_graph_name = self.convert_pattern_value_id(graph_name, variables, &mut inner_variables); @@ -251,8 +263,8 @@ impl<'a> PlanBuilder<'a> { graph_name: &PatternValue, ) -> Result { match pattern { - GraphPattern::Bgp(p) => { - for triple in sort_bgp(p) { + GraphPattern::Bgp { patterns } => { + for triple in sort_bgp(patterns) { plan = PlanNode::QuadPatternJoin { child: Rc::new(plan), subject: self @@ -278,9 +290,8 @@ impl<'a> PlanBuilder<'a> { object: self.pattern_value_from_term_or_variable(object, variables), graph_name: graph_name.clone(), }), - GraphPattern::Graph { inner, graph_name } => { - let graph_name = - self.pattern_value_from_named_node_or_variable(graph_name, variables); + GraphPattern::Graph { inner, name } => { + let graph_name = self.pattern_value_from_named_node_or_variable(name, variables); self.build_sequence(plan, inner, variables, &graph_name) } GraphPattern::Sequence(elements) => elements.iter().fold(Ok(plan), |plan, element| { @@ -882,12 +893,12 @@ impl<'a> PlanBuilder<'a> { fn build_for_aggregate( &mut self, - aggregate: &AggregationFunction, + aggregate: &AggregateExpression, variables: &mut Vec, graph_name: &PatternValue, ) -> Result { match aggregate { - AggregationFunction::Count { expr, distinct } => Ok(PlanAggregation { + AggregateExpression::Count { expr, distinct } => Ok(PlanAggregation { function: PlanAggregationFunction::Count, parameter: match expr { Some(expr) => Some(self.build_for_expression(expr, variables, graph_name)?), @@ -895,32 +906,32 @@ impl<'a> PlanBuilder<'a> { }, distinct: *distinct, }), - AggregationFunction::Sum { expr, distinct } => Ok(PlanAggregation { + AggregateExpression::Sum { expr, distinct } => Ok(PlanAggregation { function: PlanAggregationFunction::Sum, parameter: Some(self.build_for_expression(expr, variables, graph_name)?), distinct: *distinct, }), - AggregationFunction::Min { expr, distinct } => Ok(PlanAggregation { + AggregateExpression::Min { expr, distinct } => Ok(PlanAggregation { function: PlanAggregationFunction::Min, parameter: Some(self.build_for_expression(expr, variables, graph_name)?), distinct: *distinct, }), - AggregationFunction::Max { expr, distinct } => Ok(PlanAggregation { + AggregateExpression::Max { expr, distinct } => Ok(PlanAggregation { function: PlanAggregationFunction::Max, parameter: Some(self.build_for_expression(expr, variables, graph_name)?), distinct: *distinct, }), - AggregationFunction::Avg { expr, distinct } => Ok(PlanAggregation { + AggregateExpression::Avg { expr, distinct } => Ok(PlanAggregation { function: PlanAggregationFunction::Avg, parameter: Some(self.build_for_expression(expr, variables, graph_name)?), distinct: *distinct, }), - AggregationFunction::Sample { expr, distinct } => Ok(PlanAggregation { + AggregateExpression::Sample { expr, distinct } => Ok(PlanAggregation { function: PlanAggregationFunction::Sample, parameter: Some(self.build_for_expression(expr, variables, graph_name)?), distinct: *distinct, }), - AggregationFunction::GroupConcat { + AggregateExpression::GroupConcat { expr, distinct, separator, @@ -931,7 +942,7 @@ impl<'a> PlanBuilder<'a> { parameter: Some(self.build_for_expression(expr, variables, graph_name)?), distinct: *distinct, }), - AggregationFunction::Custom { .. } => Err(EvaluationError::msg( + AggregateExpression::Custom { .. } => Err(EvaluationError::msg( "Custom aggregation functions are not supported yet", )), } diff --git a/lib/src/sparql/update.rs b/lib/src/sparql/update.rs index cdd0647c..744d9592 100644 --- a/lib/src/sparql/update.rs +++ b/lib/src/sparql/update.rs @@ -74,8 +74,12 @@ impl<'a> SimpleUpdateEvaluator<'a> { pattern, .. } => self.eval_delete_insert(delete, insert, using_dataset.as_ref().unwrap(), pattern), - GraphUpdateOperation::Load { silent, from, to } => { - if let Err(error) = self.eval_load(from, to) { + GraphUpdateOperation::Load { + silent, + source, + destination, + } => { + if let Err(error) = self.eval_load(source, destination) { if *silent { Ok(()) } else { diff --git a/spargebra/src/algebra.rs b/spargebra/src/algebra.rs index caace3a2..02e7bc8a 100644 --- a/spargebra/src/algebra.rs +++ b/spargebra/src/algebra.rs @@ -515,7 +515,7 @@ impl fmt::Display for Function { #[derive(Eq, PartialEq, Debug, Clone, Hash)] pub enum GraphPattern { /// A [basic graph pattern](https://www.w3.org/TR/sparql11-query/#defn_BasicGraphPattern) - Bgp(Vec), + Bgp { patterns: Vec }, /// A [property path pattern](https://www.w3.org/TR/sparql11-query/#defn_evalPP_predicate) Path { subject: TermPattern, @@ -531,38 +531,38 @@ pub enum GraphPattern { LeftJoin { left: Box, right: Box, - expr: Option, + expression: Option, }, /// [Filter](https://www.w3.org/TR/sparql11-query/#defn_algFilter) Filter { expr: Expression, inner: Box }, /// [Union](https://www.w3.org/TR/sparql11-query/#defn_algUnion) Union { left: Box, right: Box }, Graph { - graph_name: NamedNodePattern, + name: NamedNodePattern, inner: Box, }, /// [Extend](https://www.w3.org/TR/sparql11-query/#defn_extend) Extend { inner: Box, - var: Variable, - expr: Expression, + variable: Variable, + expression: Expression, }, /// [Minus](https://www.w3.org/TR/sparql11-query/#defn_algMinus) Minus { left: Box, right: Box }, /// A table used to provide inline values - Table { + Values { variables: Vec, - rows: Vec>>, + bindings: Vec>>, }, /// [OrderBy](https://www.w3.org/TR/sparql11-query/#defn_algOrdered) OrderBy { inner: Box, - condition: Vec, + expression: Vec, }, /// [Project](https://www.w3.org/TR/sparql11-query/#defn_algProjection) Project { inner: Box, - projection: Vec, + variables: Vec, }, /// [Distinct](https://www.w3.org/TR/sparql11-query/#defn_algDistinct) Distinct { inner: Box }, @@ -577,13 +577,13 @@ pub enum GraphPattern { /// [Group](https://www.w3.org/TR/sparql11-federated-query/#aggregateAlgebra) Group { inner: Box, - by: Vec, - aggregates: Vec<(Variable, AggregationFunction)>, + variables: Vec, + aggregates: Vec<(Variable, AggregateExpression)>, }, /// [Service](https://www.w3.org/TR/sparql11-federated-query/#defn_evalService) Service { name: NamedNodePattern, - pattern: Box, + inner: Box, silent: bool, }, } @@ -592,9 +592,9 @@ impl GraphPattern { /// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html). pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result { match self { - Self::Bgp(p) => { + Self::Bgp { patterns } => { write!(f, "(bgp")?; - for pattern in p { + for pattern in patterns { write!(f, " ")?; pattern.fmt_sse(f)?; } @@ -628,12 +628,16 @@ impl GraphPattern { right.fmt_sse(f)?; write!(f, ")") } - Self::LeftJoin { left, right, expr } => { + Self::LeftJoin { + left, + right, + expression, + } => { write!(f, "(leftjoin ")?; left.fmt_sse(f)?; write!(f, " ")?; right.fmt_sse(f)?; - if let Some(expr) = expr { + if let Some(expr) = expression { write!(f, " ")?; expr.fmt_sse(f)?; } @@ -653,18 +657,22 @@ impl GraphPattern { right.fmt_sse(f)?; write!(f, ")") } - Self::Graph { graph_name, inner } => { + Self::Graph { name, inner } => { write!(f, "(graph ")?; - graph_name.fmt_sse(f)?; + name.fmt_sse(f)?; write!(f, " ")?; inner.fmt_sse(f)?; write!(f, ")") } - Self::Extend { inner, var, expr } => { + Self::Extend { + inner, + variable, + expression, + } => { write!(f, "(extend ((")?; - var.fmt_sse(f)?; + variable.fmt_sse(f)?; write!(f, " ")?; - expr.fmt_sse(f)?; + expression.fmt_sse(f)?; write!(f, ")) ")?; inner.fmt_sse(f)?; write!(f, ")") @@ -678,7 +686,7 @@ impl GraphPattern { } Self::Service { name, - pattern, + inner, silent, } => { write!(f, "(service ")?; @@ -687,16 +695,16 @@ impl GraphPattern { } name.fmt_sse(f)?; write!(f, " ")?; - pattern.fmt_sse(f)?; + inner.fmt_sse(f)?; write!(f, ")") } Self::Group { inner, - by, + variables, aggregates, } => { write!(f, "(group (")?; - for (i, v) in by.iter().enumerate() { + for (i, v) in variables.iter().enumerate() { if i > 0 { write!(f, " ")?; } @@ -717,14 +725,17 @@ impl GraphPattern { inner.fmt_sse(f)?; write!(f, ")") } - Self::Table { variables, rows } => { + Self::Values { + variables, + bindings, + } => { write!(f, "(table (vars")?; for var in variables { write!(f, " ")?; var.fmt_sse(f)?; } write!(f, ")")?; - for row in rows { + for row in bindings { write!(f, " (row")?; for (value, var) in row.iter().zip(variables) { if let Some(value) = value { @@ -739,9 +750,9 @@ impl GraphPattern { } write!(f, ")") } - Self::OrderBy { inner, condition } => { + Self::OrderBy { inner, expression } => { write!(f, "(order (")?; - for (i, c) in condition.iter().enumerate() { + for (i, c) in expression.iter().enumerate() { if i > 0 { write!(f, " ")?; } @@ -751,9 +762,9 @@ impl GraphPattern { inner.fmt_sse(f)?; write!(f, ")") } - Self::Project { inner, projection } => { + Self::Project { inner, variables } => { write!(f, "(project (")?; - for (i, v) in projection.iter().enumerate() { + for (i, v) in variables.iter().enumerate() { if i > 0 { write!(f, " ")?; } @@ -793,8 +804,8 @@ impl GraphPattern { impl fmt::Display for GraphPattern { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Self::Bgp(p) => { - for pattern in p { + Self::Bgp { patterns } => { + for pattern in patterns { write!(f, "{} .", pattern)? } Ok(()) @@ -824,8 +835,12 @@ impl fmt::Display for GraphPattern { write!(f, "{} {}", left, right) } } - Self::LeftJoin { left, right, expr } => { - if let Some(expr) = expr { + Self::LeftJoin { + left, + right, + expression, + } => { + if let Some(expr) = expression { write!(f, "{} OPTIONAL {{ {} FILTER({}) }}", left, right, expr) } else { write!(f, "{} OPTIONAL {{ {} }}", left, right) @@ -835,29 +850,36 @@ impl fmt::Display for GraphPattern { write!(f, "{} FILTER({})", inner, expr) } Self::Union { left, right } => write!(f, "{{ {} }} UNION {{ {} }}", left, right,), - Self::Graph { graph_name, inner } => { - write!(f, "GRAPH {} {{ {} }}", graph_name, inner) + Self::Graph { name, inner } => { + write!(f, "GRAPH {} {{ {} }}", name, inner) } - Self::Extend { inner, var, expr } => write!(f, "{} BIND({} AS {})", inner, expr, var), + Self::Extend { + inner, + variable, + expression, + } => write!(f, "{} BIND({} AS {})", inner, expression, variable), Self::Minus { left, right } => write!(f, "{} MINUS {{ {} }}", left, right), Self::Service { name, - pattern, + inner, silent, } => { if *silent { - write!(f, "SERVICE SILENT {} {{ {} }}", name, pattern) + write!(f, "SERVICE SILENT {} {{ {} }}", name, inner) } else { - write!(f, "SERVICE {} {{ {} }}", name, pattern) + write!(f, "SERVICE {} {{ {} }}", name, inner) } } - Self::Table { variables, rows } => { + Self::Values { + variables, + bindings, + } => { write!(f, "VALUES ( ")?; for var in variables { write!(f, "{} ", var)?; } write!(f, ") {{ ")?; - for row in rows { + for row in bindings { write!(f, "( ")?; for val in row { match val { @@ -871,20 +893,20 @@ impl fmt::Display for GraphPattern { } Self::Group { inner, - by, + variables, aggregates, } => { write!(f, "{{SELECT")?; for (a, v) in aggregates { write!(f, " ({} AS {})", v, a)?; } - for b in by { + for b in variables { write!(f, " {}", b)?; } write!(f, " WHERE {{ {} }}", inner)?; - if !by.is_empty() { + if !variables.is_empty() { write!(f, " GROUP BY")?; - for v in by { + for v in variables { write!(f, " {}", v)?; } } @@ -904,7 +926,9 @@ impl fmt::Display for GraphPattern { impl Default for GraphPattern { fn default() -> Self { - Self::Bgp(Vec::default()) + Self::Bgp { + patterns: Vec::default(), + } } } @@ -916,8 +940,8 @@ impl GraphPattern { fn lookup_in_scope_variables<'a>(&'a self, callback: &mut impl FnMut(&'a Variable)) { match self { - Self::Bgp(p) => { - for pattern in p { + Self::Bgp { patterns } => { + for pattern in patterns { lookup_triple_pattern_variables(pattern, callback) } } @@ -950,33 +974,39 @@ impl GraphPattern { left.lookup_in_scope_variables(callback); right.lookup_in_scope_variables(callback); } - Self::Graph { graph_name, inner } => { - if let NamedNodePattern::Variable(ref g) = graph_name { + Self::Graph { name, inner } => { + if let NamedNodePattern::Variable(ref g) = name { callback(g); } inner.lookup_in_scope_variables(callback); } - Self::Extend { inner, var, .. } => { - callback(var); + Self::Extend { + inner, variable, .. + } => { + callback(variable); inner.lookup_in_scope_variables(callback); } Self::Minus { left, .. } => left.lookup_in_scope_variables(callback), - Self::Service { pattern, .. } => pattern.lookup_in_scope_variables(callback), - Self::Group { by, aggregates, .. } => { - for v in by { + Self::Service { inner, .. } => inner.lookup_in_scope_variables(callback), + Self::Group { + variables, + aggregates, + .. + } => { + for v in variables { callback(v); } for (v, _) in aggregates { callback(v); } } - Self::Table { variables, .. } => { + Self::Values { variables, .. } => { for v in variables { callback(v); } } - Self::Project { projection, .. } => { - for v in projection { + Self::Project { variables, .. } => { + for v in variables { callback(v); } } @@ -1029,12 +1059,12 @@ impl<'a> fmt::Display for SparqlGraphRootPattern<'a> { let mut child = self.pattern; loop { match child { - GraphPattern::OrderBy { inner, condition } => { - order = Some(condition); + GraphPattern::OrderBy { inner, expression } => { + order = Some(expression); child = &*inner; } - GraphPattern::Project { inner, projection } if project.is_empty() => { - project = projection; + GraphPattern::Project { inner, variables } if project.is_empty() => { + project = variables; child = &*inner; } GraphPattern::Distinct { inner } => { @@ -1094,7 +1124,7 @@ impl<'a> fmt::Display for SparqlGraphRootPattern<'a> { /// A set function used in aggregates (c.f. [`GraphPattern::Group`]) #[derive(Eq, PartialEq, Debug, Clone, Hash)] -pub enum AggregationFunction { +pub enum AggregateExpression { /// [Count](https://www.w3.org/TR/sparql11-query/#defn_aggCount) Count { expr: Option>, @@ -1139,7 +1169,7 @@ pub enum AggregationFunction { }, } -impl AggregationFunction { +impl AggregateExpression { /// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html). pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result { match self { @@ -1228,7 +1258,7 @@ impl AggregationFunction { } } -impl fmt::Display for AggregationFunction { +impl fmt::Display for AggregateExpression { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Count { expr, distinct } => { @@ -1317,14 +1347,14 @@ impl fmt::Display for AggregationFunction { /// An ordering comparator used by [`GraphPattern::OrderBy`] #[derive(Eq, PartialEq, Debug, Clone, Hash)] -pub enum OrderComparator { +pub enum OrderExpression { /// Ascending order Asc(Expression), /// Descending order Desc(Expression), } -impl OrderComparator { +impl OrderExpression { /// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html). pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result { match self { @@ -1342,7 +1372,7 @@ impl OrderComparator { } } -impl fmt::Display for OrderComparator { +impl fmt::Display for OrderExpression { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Asc(e) => write!(f, "ASC({})", e), diff --git a/spargebra/src/parser.rs b/spargebra/src/parser.rs index 4fd02af3..e0f5e921 100644 --- a/spargebra/src/parser.rs +++ b/spargebra/src/parser.rs @@ -262,7 +262,9 @@ fn build_bgp(patterns: Vec) -> GraphPattern { object, } => { if !bgp.is_empty() { - elements.push(GraphPattern::Bgp(take(&mut bgp))); + elements.push(GraphPattern::Bgp { + patterns: take(&mut bgp), + }); } elements.push(GraphPattern::Path { subject, @@ -273,7 +275,7 @@ fn build_bgp(patterns: Vec) -> GraphPattern { } } if !bgp.is_empty() { - elements.push(GraphPattern::Bgp(bgp)); + elements.push(GraphPattern::Bgp { patterns: bgp }); } new_sequence(elements) } @@ -355,12 +357,12 @@ enum PartialGraphPattern { fn new_join(l: GraphPattern, r: GraphPattern) -> GraphPattern { //Avoid to output empty BGPs - if let GraphPattern::Bgp(pl) = &l { + if let GraphPattern::Bgp { patterns: pl } = &l { if pl.is_empty() { return r; } } - if let GraphPattern::Bgp(pr) = &r { + if let GraphPattern::Bgp { patterns: pr } = &r { if pr.is_empty() { return l; } @@ -369,39 +371,33 @@ fn new_join(l: GraphPattern, r: GraphPattern) -> GraphPattern { // Some optimizations // TODO: move to a specific optimizer pass match (l, r) { - (GraphPattern::Bgp(mut pl), GraphPattern::Bgp(pr)) => { + (GraphPattern::Bgp { patterns: mut pl }, GraphPattern::Bgp { patterns: pr }) => { pl.extend(pr); - GraphPattern::Bgp(pl) + 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 { .. }) => + 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 { .. }) => + if matches!(l, GraphPattern::Bgp { .. } | GraphPattern::Path { .. }) => { e.insert(0, l); GraphPattern::Sequence(e) } ( - GraphPattern::Graph { - graph_name: g1, - inner: l, - }, - GraphPattern::Graph { - graph_name: g2, - inner: r, - }, + GraphPattern::Graph { name: g1, inner: l }, + GraphPattern::Graph { name: g2, inner: r }, ) if g1 == g2 => { // We merge identical graphs GraphPattern::Graph { - graph_name: g1, + name: g1, inner: Box::new(new_join(*l, *r)), } } @@ -414,7 +410,7 @@ fn new_join(l: GraphPattern, r: GraphPattern) -> GraphPattern { fn new_sequence(elements: Vec) -> GraphPattern { match elements.len() { - 0 => GraphPattern::Bgp(vec![]), + 0 => GraphPattern::default(), 1 => elements.into_iter().next().unwrap(), _ => GraphPattern::Sequence(elements), } @@ -467,7 +463,7 @@ fn build_select( wher: GraphPattern, mut group: Option<(Vec, Vec<(Expression, Variable)>)>, having: Option, - order_by: Option>, + order_by: Option>, offset_limit: Option<(usize, Option)>, values: Option, state: &mut ParserState, @@ -482,16 +478,16 @@ fn build_select( } if let Some((clauses, binds)) = group { - for (expr, var) in binds { + for (expression, variable) in binds { p = GraphPattern::Extend { inner: Box::new(p), - var, - expr, + variable, + expression, }; } p = GraphPattern::Group { inner: Box::new(p), - by: clauses, + variables: clauses, aggregates, }; with_aggregate = true; @@ -527,14 +523,14 @@ fn build_select( } v } - SelectionMember::Expression(expr, v) => { - if visible.contains(&v) { + SelectionMember::Expression(expression, variable) => { + if visible.contains(&variable) { // We disallow to override an existing variable with an expression return Err( "The SELECT overrides an existing variable using an expression", ); } - if with_aggregate && !are_variables_bound(&expr, &visible) { + if with_aggregate && !are_variables_bound(&expression, &visible) { // We validate projection variables if there is an aggregate return Err( "The SELECT contains an exprssion with a variable that is unbound", @@ -542,10 +538,10 @@ fn build_select( } p = GraphPattern::Extend { inner: Box::new(p), - var: v.clone(), - expr, + variable: variable.clone(), + expression, }; - v + variable } }; if pv.contains(&v) { @@ -574,10 +570,10 @@ fn build_select( let mut m = p; //ORDER BY - if let Some(condition) = order_by { + if let Some(expression) = order_by { m = GraphPattern::OrderBy { inner: Box::new(m), - condition, + expression, }; } @@ -585,7 +581,7 @@ fn build_select( if with_project { m = GraphPattern::Project { inner: Box::new(m), - projection: pv, + variables: pv, }; } match select.option { @@ -645,11 +641,13 @@ fn are_variables_bound(expression: &Expression, variables: &HashSet) - } fn copy_graph(from: impl Into, to: impl Into) -> GraphUpdateOperation { - let bgp = GraphPattern::Bgp(vec![TriplePattern::new( - Variable { name: "s".into() }, - Variable { name: "p".into() }, - Variable { name: "o".into() }, - )]); + let bgp = GraphPattern::Bgp { + patterns: vec![TriplePattern::new( + Variable { name: "s".into() }, + Variable { name: "p".into() }, + Variable { name: "o".into() }, + )], + }; GraphUpdateOperation::DeleteInsert { delete: Vec::new(), insert: vec![QuadPattern::new( @@ -661,7 +659,7 @@ fn copy_graph(from: impl Into, to: impl Into) -> Gr using: None, pattern: Box::new(match from.into() { GraphName::NamedNode(from) => GraphPattern::Graph { - graph_name: from.into(), + name: from.into(), inner: Box::new(bgp), }, GraphName::DefaultGraph => bgp, @@ -679,7 +677,7 @@ pub struct ParserState { namespaces: HashMap, used_bnodes: HashSet, currently_used_bnodes: HashSet, - aggregates: Vec>, + aggregates: Vec>, } impl ParserState { @@ -691,7 +689,7 @@ impl ParserState { } } - fn new_aggregation(&mut self, agg: AggregationFunction) -> Result { + fn new_aggregation(&mut self, agg: AggregateExpression) -> Result { let aggregates = self.aggregates.last_mut().ok_or("Unexpected aggregate")?; Ok(aggregates .iter() @@ -1003,7 +1001,7 @@ parser! { dataset: d, pattern: build_select( Selection::no_op(), - GraphPattern::Bgp(c), + GraphPattern::Bgp { patterns: c }, g, h, o, l, v, state )?, base_iri: state.base_iri.clone() @@ -1117,15 +1115,15 @@ parser! { rule HavingCondition() -> Expression = Constraint() //[23] - rule OrderClause() -> Vec = i("ORDER") _ i("BY") _ c:OrderClause_item()+ { c } - rule OrderClause_item() -> OrderComparator = c:OrderCondition() _ { c } + rule OrderClause() -> Vec = i("ORDER") _ i("BY") _ c:OrderClause_item()+ { c } + rule OrderClause_item() -> OrderExpression = c:OrderCondition() _ { c } //[24] - rule OrderCondition() -> OrderComparator = - i("ASC") _ e: BrackettedExpression() { OrderComparator::Asc(e) } / - i("DESC") _ e: BrackettedExpression() { OrderComparator::Desc(e) } / - e: Constraint() { OrderComparator::Asc(e) } / - v: Var() { OrderComparator::Asc(Expression::from(v)) } + rule OrderCondition() -> OrderExpression = + i("ASC") _ e: BrackettedExpression() { OrderExpression::Asc(e) } / + i("DESC") _ e: BrackettedExpression() { OrderExpression::Desc(e) } / + e: Constraint() { OrderExpression::Asc(e) } / + v: Var() { OrderExpression::Asc(Expression::from(v)) } //[25] rule LimitOffsetClauses() -> (usize, Option) = @@ -1156,8 +1154,8 @@ parser! { rule Update1_silent() -> bool = i("SILENT") { true } / { false } //[31] - rule Load() -> Vec = i("LOAD") _ silent:Update1_silent() _ from:iri() _ to:Load_to()? { - vec![GraphUpdateOperation::Load { silent, from, to: to.map_or(GraphName::DefaultGraph, GraphName::NamedNode) }] + rule Load() -> Vec = i("LOAD") _ silent:Update1_silent() _ source:iri() _ destination:Load_to()? { + vec![GraphUpdateOperation::Load { silent, source, destination: destination.map_or(GraphName::DefaultGraph, GraphName::NamedNode) }] } rule Load_to() -> NamedNode = i("INTO") _ g: GraphRef() { g } @@ -1182,7 +1180,7 @@ parser! { if from == to { Vec::new() // identity case } else { - let bgp = GraphPattern::Bgp(vec![TriplePattern::new(Variable { name: "s".into() }, Variable { name: "p".into() }, Variable { name: "o".into() })]); + let bgp = GraphPattern::Bgp { patterns: vec![TriplePattern::new(Variable { name: "s".into() }, Variable { name: "p".into() }, Variable { name: "o".into() })] }; vec![copy_graph(from, to)] } } @@ -1193,7 +1191,7 @@ parser! { if from == to { Vec::new() // identity case } else { - let bgp = GraphPattern::Bgp(vec![TriplePattern::new(Variable { name: "s".into() }, Variable { name: "p".into() }, Variable { name: "o".into() })]); + let bgp = GraphPattern::Bgp { patterns: vec![TriplePattern::new(Variable { name: "s".into() }, Variable { name: "p".into() }, Variable { name: "o".into() })] }; vec![GraphUpdateOperation::Drop { silent: true, graph: to.clone().into() }, copy_graph(from.clone(), to), GraphUpdateOperation::Drop { silent, graph: from.into() }] } } @@ -1204,7 +1202,7 @@ parser! { if from == to { Vec::new() // identity case } else { - let bgp = GraphPattern::Bgp(vec![TriplePattern::new(Variable { name: "s".into() }, Variable { name: "p".into() }, Variable{ name: "o".into() })]); + let bgp = GraphPattern::Bgp { patterns: vec![TriplePattern::new(Variable { name: "s".into() }, Variable { name: "p".into() }, Variable{ name: "o".into() })] }; vec![GraphUpdateOperation::Drop { silent: true, graph: to.clone().into() }, copy_graph(from, to)] } } @@ -1222,11 +1220,11 @@ parser! { //[40] rule DeleteWhere() -> Vec = i("DELETE") _ i("WHERE") _ d:QuadPattern() {? let pattern = new_sequence(d.iter().map(|q| { - let bgp = GraphPattern::Bgp(vec![TriplePattern::new(q.subject.clone(), q.predicate.clone(), q.object.clone())]); + 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 { graph_name: graph_name.clone().into(), inner: Box::new(bgp) }, + GraphNamePattern::NamedNode(graph_name) => GraphPattern::Graph { name: graph_name.clone().into(), inner: Box::new(bgp) }, GraphNamePattern::DefaultGraph => bgp, - GraphNamePattern::Variable(graph_name) => GraphPattern::Graph { graph_name: graph_name.clone().into(), inner: Box::new(bgp) }, + GraphNamePattern::Variable(graph_name) => GraphPattern::Graph { name: graph_name.clone().into(), inner: Box::new(bgp) }, } }).collect()); let delete = d.into_iter().map(GroundQuadPattern::try_from).collect::,_>>().map_err(|_| "Blank nodes are not allowed in DELETE WHERE")?; @@ -1393,22 +1391,22 @@ parser! { for e in b.into_iter().flatten() { match e { PartialGraphPattern::Optional(p, f) => { - g = GraphPattern::LeftJoin { left: Box::new(g), right: Box::new(p), expr: f } + g = GraphPattern::LeftJoin { left: Box::new(g), right: Box::new(p), expression: f } } PartialGraphPattern::Minus(p) => { g = GraphPattern::Minus { left: Box::new(g), right: Box::new(p) } } - PartialGraphPattern::Bind(expr, var) => { + PartialGraphPattern::Bind(expression, variable) => { let mut contains = false; g.on_in_scope_variable(|v| { - if *v == var { + if *v == variable { contains = true; } }); if contains { return Err("BIND is overriding an existing variable") } - g = GraphPattern::Extend { inner: Box::new(g), var, expr } + g = GraphPattern::Extend { inner: Box::new(g), variable, expression } } PartialGraphPattern::Filter(expr) => filter = Some(if let Some(f) = filter { Expression::And(Box::new(f), Box::new(expr)) @@ -1458,14 +1456,14 @@ parser! { } //[58] - rule GraphGraphPattern() -> PartialGraphPattern = i("GRAPH") _ graph_name:VarOrIri() _ p:GroupGraphPattern() { - PartialGraphPattern::Other(GraphPattern::Graph { graph_name, inner: Box::new(p) }) + rule GraphGraphPattern() -> PartialGraphPattern = i("GRAPH") _ name:VarOrIri() _ p:GroupGraphPattern() { + PartialGraphPattern::Other(GraphPattern::Graph { name, inner: Box::new(p) }) } //[59] rule ServiceGraphPattern() -> PartialGraphPattern = - 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 }) } + i("SERVICE") _ i("SILENT") _ name:VarOrIri() _ p:GroupGraphPattern() { PartialGraphPattern::Other(GraphPattern::Service { name, inner: Box::new(p), silent: true }) } / + i("SERVICE") _ name:VarOrIri() _ p:GroupGraphPattern() { PartialGraphPattern::Other(GraphPattern::Service{ name, inner: Box::new(p), silent: true }) } //[60] rule Bind() -> PartialGraphPattern = i("BIND") _ "(" _ e:Expression() _ i("AS") _ v:Var() _ ")" { @@ -1477,7 +1475,7 @@ parser! { //[62] rule DataBlock() -> GraphPattern = l:(InlineDataOneVar() / InlineDataFull()) { - GraphPattern::Table { variables: l.0, rows: l.1 } + GraphPattern::Values { variables: l.0, bindings: l.1 } } //[63] @@ -2085,27 +2083,27 @@ parser! { rule NotExistsFunc() -> Expression = i("NOT") _ i("EXISTS") _ p:GroupGraphPattern() { Expression::Not(Box::new(Expression::Exists(Box::new(p)))) } //[127] - rule Aggregate() -> AggregationFunction = - i("COUNT") _ "(" _ i("DISTINCT") _ "*" _ ")" { AggregationFunction::Count { expr: None, distinct: true } } / - i("COUNT") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregationFunction::Count { expr: Some(Box::new(e)), distinct: true } } / - i("COUNT") _ "(" _ "*" _ ")" { AggregationFunction::Count { expr: None, distinct: false } } / - i("COUNT") _ "(" _ e:Expression() _ ")" { AggregationFunction::Count { expr: Some(Box::new(e)), distinct: false } } / - i("SUM") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregationFunction::Sum { expr: Box::new(e), distinct: true } } / - i("SUM") _ "(" _ e:Expression() _ ")" { AggregationFunction::Sum { expr: Box::new(e), distinct: false } } / - i("MIN") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregationFunction::Min { expr: Box::new(e), distinct: true } } / - i("MIN") _ "(" _ e:Expression() _ ")" { AggregationFunction::Min { expr: Box::new(e), distinct: false } } / - i("MAX") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregationFunction::Max { expr: Box::new(e), distinct: true } } / - i("MAX") _ "(" _ e:Expression() _ ")" { AggregationFunction::Max { expr: Box::new(e), distinct: false } } / - i("AVG") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregationFunction::Avg { expr: Box::new(e), distinct: true } } / - i("AVG") _ "(" _ e:Expression() _ ")" { AggregationFunction::Avg { expr: Box::new(e), distinct: false } } / - i("SAMPLE") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregationFunction::Sample { expr: Box::new(e), distinct: true } } / - i("SAMPLE") _ "(" _ e:Expression() _ ")" { AggregationFunction::Sample { expr: Box::new(e), distinct: false } } / - i("GROUP_CONCAT") _ "(" _ i("DISTINCT") _ e:Expression() _ ";" _ i("SEPARATOR") _ "=" _ s:String() _ ")" { AggregationFunction::GroupConcat { expr: Box::new(e), distinct: true, separator: Some(s) } } / - i("GROUP_CONCAT") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregationFunction::GroupConcat { expr: Box::new(e), distinct: true, separator: None } } / - i("GROUP_CONCAT") _ "(" _ e:Expression() _ ";" _ i("SEPARATOR") _ "=" _ s:String() _ ")" { AggregationFunction::GroupConcat { expr: Box::new(e), distinct: true, separator: Some(s) } } / - i("GROUP_CONCAT") _ "(" _ e:Expression() _ ")" { AggregationFunction::GroupConcat { expr: Box::new(e), distinct: false, separator: None } } / - name:iri() _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregationFunction::Custom { name, expr: Box::new(e), distinct: true } } / - name:iri() _ "(" _ e:Expression() _ ")" { AggregationFunction::Custom { name, expr: Box::new(e), distinct: false } } + rule Aggregate() -> AggregateExpression = + i("COUNT") _ "(" _ i("DISTINCT") _ "*" _ ")" { AggregateExpression::Count { expr: None, distinct: true } } / + i("COUNT") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregateExpression::Count { expr: Some(Box::new(e)), distinct: true } } / + i("COUNT") _ "(" _ "*" _ ")" { AggregateExpression::Count { expr: None, distinct: false } } / + i("COUNT") _ "(" _ e:Expression() _ ")" { AggregateExpression::Count { expr: Some(Box::new(e)), distinct: false } } / + i("SUM") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregateExpression::Sum { expr: Box::new(e), distinct: true } } / + i("SUM") _ "(" _ e:Expression() _ ")" { AggregateExpression::Sum { expr: Box::new(e), distinct: false } } / + i("MIN") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregateExpression::Min { expr: Box::new(e), distinct: true } } / + i("MIN") _ "(" _ e:Expression() _ ")" { AggregateExpression::Min { expr: Box::new(e), distinct: false } } / + i("MAX") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregateExpression::Max { expr: Box::new(e), distinct: true } } / + i("MAX") _ "(" _ e:Expression() _ ")" { AggregateExpression::Max { expr: Box::new(e), distinct: false } } / + i("AVG") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregateExpression::Avg { expr: Box::new(e), distinct: true } } / + i("AVG") _ "(" _ e:Expression() _ ")" { AggregateExpression::Avg { expr: Box::new(e), distinct: false } } / + i("SAMPLE") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregateExpression::Sample { expr: Box::new(e), distinct: true } } / + i("SAMPLE") _ "(" _ e:Expression() _ ")" { AggregateExpression::Sample { expr: Box::new(e), distinct: false } } / + i("GROUP_CONCAT") _ "(" _ i("DISTINCT") _ e:Expression() _ ";" _ i("SEPARATOR") _ "=" _ s:String() _ ")" { AggregateExpression::GroupConcat { expr: Box::new(e), distinct: true, separator: Some(s) } } / + i("GROUP_CONCAT") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregateExpression::GroupConcat { expr: Box::new(e), distinct: true, separator: None } } / + i("GROUP_CONCAT") _ "(" _ e:Expression() _ ";" _ i("SEPARATOR") _ "=" _ s:String() _ ")" { AggregateExpression::GroupConcat { expr: Box::new(e), distinct: true, separator: Some(s) } } / + i("GROUP_CONCAT") _ "(" _ e:Expression() _ ")" { AggregateExpression::GroupConcat { expr: Box::new(e), distinct: false, separator: None } } / + name:iri() _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregateExpression::Custom { name, expr: Box::new(e), distinct: true } } / + name:iri() _ "(" _ e:Expression() _ ")" { AggregateExpression::Custom { name, expr: Box::new(e), distinct: false } } //[128] rule iriOrFunction() -> Expression = i: iri() _ a: ArgList()? { diff --git a/spargebra/src/update.rs b/spargebra/src/update.rs index ad60535e..4e584d95 100644 --- a/spargebra/src/update.rs +++ b/spargebra/src/update.rs @@ -110,8 +110,8 @@ pub enum GraphUpdateOperation { /// [load](https://www.w3.org/TR/sparql11-update/#defn_loadOperation) Load { silent: bool, - from: NamedNode, - to: GraphName, + source: NamedNode, + destination: GraphName, }, /// [clear](https://www.w3.org/TR/sparql11-update/#defn_clearOperation) Clear { silent: bool, graph: GraphTarget }, @@ -183,14 +183,18 @@ impl GraphUpdateOperation { } write!(f, ")") } - GraphUpdateOperation::Load { silent, from, to } => { + GraphUpdateOperation::Load { + silent, + source, + destination, + } => { write!(f, "(load ")?; if *silent { write!(f, "silent ")?; } - from.fmt_sse(f)?; + source.fmt_sse(f)?; write!(f, " ")?; - to.fmt_sse(f)?; + destination.fmt_sse(f)?; write!(f, ")") } GraphUpdateOperation::Clear { silent, graph } => { @@ -273,14 +277,18 @@ impl fmt::Display for GraphUpdateOperation { } ) } - GraphUpdateOperation::Load { silent, from, to } => { + GraphUpdateOperation::Load { + silent, + source, + destination, + } => { write!(f, "LOAD ")?; if *silent { write!(f, "SILENT ")?; } - write!(f, "{}", from)?; - if to != &GraphName::DefaultGraph { - write!(f, " INTO GRAPH {}", to)?; + write!(f, "{}", source)?; + if destination != &GraphName::DefaultGraph { + write!(f, " INTO GRAPH {}", destination)?; } Ok(()) }