spargebra: Renamings to move closer to SPARQLAlgebra.js

pull/171/head
Tpt 3 years ago
parent 969bb69fab
commit aa9afe4641
  1. 81
      lib/src/sparql/plan_builder.rs
  2. 8
      lib/src/sparql/update.rs
  3. 170
      spargebra/src/algebra.rs
  4. 170
      spargebra/src/parser.rs
  5. 26
      spargebra/src/update.rs

@ -43,14 +43,20 @@ impl<'a> PlanBuilder<'a> {
graph_name: &PatternValue, graph_name: &PatternValue,
) -> Result<PlanNode, EvaluationError> { ) -> Result<PlanNode, EvaluationError> {
Ok(match pattern { Ok(match pattern {
GraphPattern::Bgp(_) | GraphPattern::Path { .. } | GraphPattern::Sequence { .. } => { GraphPattern::Bgp { .. }
| GraphPattern::Path { .. }
| GraphPattern::Sequence { .. } => {
self.build_sequence(PlanNode::Init, pattern, variables, graph_name)? self.build_sequence(PlanNode::Init, pattern, variables, graph_name)?
} }
GraphPattern::Join { left, right } => PlanNode::Join { GraphPattern::Join { left, right } => PlanNode::Join {
left: Rc::new(self.build_for_graph_pattern(left, variables, graph_name)?), left: Rc::new(self.build_for_graph_pattern(left, variables, graph_name)?),
right: Rc::new(self.build_for_graph_pattern(right, 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 left = self.build_for_graph_pattern(left, variables, graph_name)?;
let right = self.build_for_graph_pattern(right, 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); self.add_left_join_problematic_variables(&right, &mut possible_problem_vars);
//We add the extra filter if needed //We add the extra filter if needed
let right = if let Some(expr) = expr { let right = if let Some(expr) = expression {
PlanNode::Filter { PlanNode::Filter {
child: Rc::new(right), child: Rc::new(right),
expression: Rc::new( expression: Rc::new(
@ -97,15 +103,18 @@ impl<'a> PlanBuilder<'a> {
} }
PlanNode::Union { children } PlanNode::Union { children }
} }
GraphPattern::Graph { graph_name, inner } => { GraphPattern::Graph { name, inner } => {
let graph_name = let graph_name = self.pattern_value_from_named_node_or_variable(name, variables);
self.pattern_value_from_named_node_or_variable(graph_name, variables);
self.build_for_graph_pattern(inner, variables, &graph_name)? 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)?), child: Rc::new(self.build_for_graph_pattern(inner, variables, graph_name)?),
position: variable_key(variables, var), position: variable_key(variables, variable),
expression: Rc::new(self.build_for_expression(expr, variables, graph_name)?), expression: Rc::new(self.build_for_expression(expression, variables, graph_name)?),
}, },
GraphPattern::Minus { left, right } => PlanNode::AntiJoin { GraphPattern::Minus { left, right } => PlanNode::AntiJoin {
left: Rc::new(self.build_for_graph_pattern(left, variables, graph_name)?), left: Rc::new(self.build_for_graph_pattern(left, variables, graph_name)?),
@ -113,11 +122,11 @@ impl<'a> PlanBuilder<'a> {
}, },
GraphPattern::Service { GraphPattern::Service {
name, name,
pattern, inner,
silent, silent,
} => { } => {
// Child building should be at the begging in order for `variables` to be filled // Child building should be at the begging in order for `variables` to be filled
let child = self.build_for_graph_pattern(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); let service_name = self.pattern_value_from_named_node_or_variable(name, variables);
PlanNode::Service { PlanNode::Service {
service_name, service_name,
@ -128,13 +137,13 @@ impl<'a> PlanBuilder<'a> {
.collect(), .collect(),
), ),
child: Rc::new(child), child: Rc::new(child),
graph_pattern: Rc::new(*pattern.clone()), graph_pattern: Rc::new(inner.as_ref().clone()),
silent: *silent, silent: *silent,
} }
} }
GraphPattern::Group { GraphPattern::Group {
inner, inner,
by, variables: by,
aggregates, aggregates,
} => { } => {
let mut inner_variables = by.clone(); let mut inner_variables = by.clone();
@ -170,20 +179,20 @@ impl<'a> PlanBuilder<'a> {
), ),
} }
} }
GraphPattern::Table { GraphPattern::Values {
variables: table_variables, variables: table_variables,
rows, bindings,
} => PlanNode::StaticBindings { } => PlanNode::StaticBindings {
tuples: self.encode_bindings(table_variables, rows, variables), tuples: self.encode_bindings(table_variables, bindings, variables),
}, },
GraphPattern::OrderBy { inner, condition } => { GraphPattern::OrderBy { inner, expression } => {
let condition: Result<Vec<_>, EvaluationError> = condition let condition: Result<Vec<_>, EvaluationError> = expression
.iter() .iter()
.map(|comp| match comp { .map(|comp| match comp {
OrderComparator::Asc(e) => Ok(Comparator::Asc( OrderExpression::Asc(e) => Ok(Comparator::Asc(
self.build_for_expression(e, variables, graph_name)?, 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)?, self.build_for_expression(e, variables, graph_name)?,
)), )),
}) })
@ -193,7 +202,10 @@ impl<'a> PlanBuilder<'a> {
by: condition?, by: condition?,
} }
} }
GraphPattern::Project { inner, projection } => { GraphPattern::Project {
inner,
variables: projection,
} => {
let mut inner_variables = projection.clone(); let mut inner_variables = projection.clone();
let inner_graph_name = let inner_graph_name =
self.convert_pattern_value_id(graph_name, variables, &mut inner_variables); self.convert_pattern_value_id(graph_name, variables, &mut inner_variables);
@ -251,8 +263,8 @@ impl<'a> PlanBuilder<'a> {
graph_name: &PatternValue, graph_name: &PatternValue,
) -> Result<PlanNode, EvaluationError> { ) -> Result<PlanNode, EvaluationError> {
match pattern { match pattern {
GraphPattern::Bgp(p) => { GraphPattern::Bgp { patterns } => {
for triple in sort_bgp(p) { for triple in sort_bgp(patterns) {
plan = PlanNode::QuadPatternJoin { plan = PlanNode::QuadPatternJoin {
child: Rc::new(plan), child: Rc::new(plan),
subject: self subject: self
@ -278,9 +290,8 @@ impl<'a> PlanBuilder<'a> {
object: self.pattern_value_from_term_or_variable(object, variables), object: self.pattern_value_from_term_or_variable(object, variables),
graph_name: graph_name.clone(), graph_name: graph_name.clone(),
}), }),
GraphPattern::Graph { inner, graph_name } => { GraphPattern::Graph { inner, name } => {
let graph_name = let graph_name = self.pattern_value_from_named_node_or_variable(name, variables);
self.pattern_value_from_named_node_or_variable(graph_name, variables);
self.build_sequence(plan, inner, variables, &graph_name) self.build_sequence(plan, inner, variables, &graph_name)
} }
GraphPattern::Sequence(elements) => elements.iter().fold(Ok(plan), |plan, element| { GraphPattern::Sequence(elements) => elements.iter().fold(Ok(plan), |plan, element| {
@ -882,12 +893,12 @@ impl<'a> PlanBuilder<'a> {
fn build_for_aggregate( fn build_for_aggregate(
&mut self, &mut self,
aggregate: &AggregationFunction, aggregate: &AggregateExpression,
variables: &mut Vec<Variable>, variables: &mut Vec<Variable>,
graph_name: &PatternValue, graph_name: &PatternValue,
) -> Result<PlanAggregation, EvaluationError> { ) -> Result<PlanAggregation, EvaluationError> {
match aggregate { match aggregate {
AggregationFunction::Count { expr, distinct } => Ok(PlanAggregation { AggregateExpression::Count { expr, distinct } => Ok(PlanAggregation {
function: PlanAggregationFunction::Count, function: PlanAggregationFunction::Count,
parameter: match expr { parameter: match expr {
Some(expr) => Some(self.build_for_expression(expr, variables, graph_name)?), Some(expr) => Some(self.build_for_expression(expr, variables, graph_name)?),
@ -895,32 +906,32 @@ impl<'a> PlanBuilder<'a> {
}, },
distinct: *distinct, distinct: *distinct,
}), }),
AggregationFunction::Sum { expr, distinct } => Ok(PlanAggregation { AggregateExpression::Sum { expr, distinct } => Ok(PlanAggregation {
function: PlanAggregationFunction::Sum, function: PlanAggregationFunction::Sum,
parameter: Some(self.build_for_expression(expr, variables, graph_name)?), parameter: Some(self.build_for_expression(expr, variables, graph_name)?),
distinct: *distinct, distinct: *distinct,
}), }),
AggregationFunction::Min { expr, distinct } => Ok(PlanAggregation { AggregateExpression::Min { expr, distinct } => Ok(PlanAggregation {
function: PlanAggregationFunction::Min, function: PlanAggregationFunction::Min,
parameter: Some(self.build_for_expression(expr, variables, graph_name)?), parameter: Some(self.build_for_expression(expr, variables, graph_name)?),
distinct: *distinct, distinct: *distinct,
}), }),
AggregationFunction::Max { expr, distinct } => Ok(PlanAggregation { AggregateExpression::Max { expr, distinct } => Ok(PlanAggregation {
function: PlanAggregationFunction::Max, function: PlanAggregationFunction::Max,
parameter: Some(self.build_for_expression(expr, variables, graph_name)?), parameter: Some(self.build_for_expression(expr, variables, graph_name)?),
distinct: *distinct, distinct: *distinct,
}), }),
AggregationFunction::Avg { expr, distinct } => Ok(PlanAggregation { AggregateExpression::Avg { expr, distinct } => Ok(PlanAggregation {
function: PlanAggregationFunction::Avg, function: PlanAggregationFunction::Avg,
parameter: Some(self.build_for_expression(expr, variables, graph_name)?), parameter: Some(self.build_for_expression(expr, variables, graph_name)?),
distinct: *distinct, distinct: *distinct,
}), }),
AggregationFunction::Sample { expr, distinct } => Ok(PlanAggregation { AggregateExpression::Sample { expr, distinct } => Ok(PlanAggregation {
function: PlanAggregationFunction::Sample, function: PlanAggregationFunction::Sample,
parameter: Some(self.build_for_expression(expr, variables, graph_name)?), parameter: Some(self.build_for_expression(expr, variables, graph_name)?),
distinct: *distinct, distinct: *distinct,
}), }),
AggregationFunction::GroupConcat { AggregateExpression::GroupConcat {
expr, expr,
distinct, distinct,
separator, separator,
@ -931,7 +942,7 @@ impl<'a> PlanBuilder<'a> {
parameter: Some(self.build_for_expression(expr, variables, graph_name)?), parameter: Some(self.build_for_expression(expr, variables, graph_name)?),
distinct: *distinct, distinct: *distinct,
}), }),
AggregationFunction::Custom { .. } => Err(EvaluationError::msg( AggregateExpression::Custom { .. } => Err(EvaluationError::msg(
"Custom aggregation functions are not supported yet", "Custom aggregation functions are not supported yet",
)), )),
} }

@ -74,8 +74,12 @@ impl<'a> SimpleUpdateEvaluator<'a> {
pattern, pattern,
.. ..
} => self.eval_delete_insert(delete, insert, using_dataset.as_ref().unwrap(), pattern), } => self.eval_delete_insert(delete, insert, using_dataset.as_ref().unwrap(), pattern),
GraphUpdateOperation::Load { silent, from, to } => { GraphUpdateOperation::Load {
if let Err(error) = self.eval_load(from, to) { silent,
source,
destination,
} => {
if let Err(error) = self.eval_load(source, destination) {
if *silent { if *silent {
Ok(()) Ok(())
} else { } else {

@ -515,7 +515,7 @@ impl fmt::Display for Function {
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum GraphPattern { pub enum GraphPattern {
/// A [basic graph pattern](https://www.w3.org/TR/sparql11-query/#defn_BasicGraphPattern) /// A [basic graph pattern](https://www.w3.org/TR/sparql11-query/#defn_BasicGraphPattern)
Bgp(Vec<TriplePattern>), Bgp { patterns: Vec<TriplePattern> },
/// A [property path pattern](https://www.w3.org/TR/sparql11-query/#defn_evalPP_predicate) /// A [property path pattern](https://www.w3.org/TR/sparql11-query/#defn_evalPP_predicate)
Path { Path {
subject: TermPattern, subject: TermPattern,
@ -531,38 +531,38 @@ pub enum GraphPattern {
LeftJoin { LeftJoin {
left: Box<Self>, left: Box<Self>,
right: Box<Self>, right: Box<Self>,
expr: Option<Expression>, expression: Option<Expression>,
}, },
/// [Filter](https://www.w3.org/TR/sparql11-query/#defn_algFilter) /// [Filter](https://www.w3.org/TR/sparql11-query/#defn_algFilter)
Filter { expr: Expression, inner: Box<Self> }, Filter { expr: Expression, inner: Box<Self> },
/// [Union](https://www.w3.org/TR/sparql11-query/#defn_algUnion) /// [Union](https://www.w3.org/TR/sparql11-query/#defn_algUnion)
Union { left: Box<Self>, right: Box<Self> }, Union { left: Box<Self>, right: Box<Self> },
Graph { Graph {
graph_name: NamedNodePattern, name: NamedNodePattern,
inner: Box<Self>, inner: Box<Self>,
}, },
/// [Extend](https://www.w3.org/TR/sparql11-query/#defn_extend) /// [Extend](https://www.w3.org/TR/sparql11-query/#defn_extend)
Extend { Extend {
inner: Box<Self>, inner: Box<Self>,
var: Variable, variable: Variable,
expr: Expression, expression: Expression,
}, },
/// [Minus](https://www.w3.org/TR/sparql11-query/#defn_algMinus) /// [Minus](https://www.w3.org/TR/sparql11-query/#defn_algMinus)
Minus { left: Box<Self>, right: Box<Self> }, Minus { left: Box<Self>, right: Box<Self> },
/// A table used to provide inline values /// A table used to provide inline values
Table { Values {
variables: Vec<Variable>, variables: Vec<Variable>,
rows: Vec<Vec<Option<GroundTerm>>>, bindings: Vec<Vec<Option<GroundTerm>>>,
}, },
/// [OrderBy](https://www.w3.org/TR/sparql11-query/#defn_algOrdered) /// [OrderBy](https://www.w3.org/TR/sparql11-query/#defn_algOrdered)
OrderBy { OrderBy {
inner: Box<Self>, inner: Box<Self>,
condition: Vec<OrderComparator>, expression: Vec<OrderExpression>,
}, },
/// [Project](https://www.w3.org/TR/sparql11-query/#defn_algProjection) /// [Project](https://www.w3.org/TR/sparql11-query/#defn_algProjection)
Project { Project {
inner: Box<Self>, inner: Box<Self>,
projection: Vec<Variable>, variables: Vec<Variable>,
}, },
/// [Distinct](https://www.w3.org/TR/sparql11-query/#defn_algDistinct) /// [Distinct](https://www.w3.org/TR/sparql11-query/#defn_algDistinct)
Distinct { inner: Box<Self> }, Distinct { inner: Box<Self> },
@ -577,13 +577,13 @@ pub enum GraphPattern {
/// [Group](https://www.w3.org/TR/sparql11-federated-query/#aggregateAlgebra) /// [Group](https://www.w3.org/TR/sparql11-federated-query/#aggregateAlgebra)
Group { Group {
inner: Box<Self>, inner: Box<Self>,
by: Vec<Variable>, variables: Vec<Variable>,
aggregates: Vec<(Variable, AggregationFunction)>, aggregates: Vec<(Variable, AggregateExpression)>,
}, },
/// [Service](https://www.w3.org/TR/sparql11-federated-query/#defn_evalService) /// [Service](https://www.w3.org/TR/sparql11-federated-query/#defn_evalService)
Service { Service {
name: NamedNodePattern, name: NamedNodePattern,
pattern: Box<Self>, inner: Box<Self>,
silent: bool, silent: bool,
}, },
} }
@ -592,9 +592,9 @@ impl GraphPattern {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html). /// 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 { pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
match self { match self {
Self::Bgp(p) => { Self::Bgp { patterns } => {
write!(f, "(bgp")?; write!(f, "(bgp")?;
for pattern in p { for pattern in patterns {
write!(f, " ")?; write!(f, " ")?;
pattern.fmt_sse(f)?; pattern.fmt_sse(f)?;
} }
@ -628,12 +628,16 @@ impl GraphPattern {
right.fmt_sse(f)?; right.fmt_sse(f)?;
write!(f, ")") write!(f, ")")
} }
Self::LeftJoin { left, right, expr } => { Self::LeftJoin {
left,
right,
expression,
} => {
write!(f, "(leftjoin ")?; write!(f, "(leftjoin ")?;
left.fmt_sse(f)?; left.fmt_sse(f)?;
write!(f, " ")?; write!(f, " ")?;
right.fmt_sse(f)?; right.fmt_sse(f)?;
if let Some(expr) = expr { if let Some(expr) = expression {
write!(f, " ")?; write!(f, " ")?;
expr.fmt_sse(f)?; expr.fmt_sse(f)?;
} }
@ -653,18 +657,22 @@ impl GraphPattern {
right.fmt_sse(f)?; right.fmt_sse(f)?;
write!(f, ")") write!(f, ")")
} }
Self::Graph { graph_name, inner } => { Self::Graph { name, inner } => {
write!(f, "(graph ")?; write!(f, "(graph ")?;
graph_name.fmt_sse(f)?; name.fmt_sse(f)?;
write!(f, " ")?; write!(f, " ")?;
inner.fmt_sse(f)?; inner.fmt_sse(f)?;
write!(f, ")") write!(f, ")")
} }
Self::Extend { inner, var, expr } => { Self::Extend {
inner,
variable,
expression,
} => {
write!(f, "(extend ((")?; write!(f, "(extend ((")?;
var.fmt_sse(f)?; variable.fmt_sse(f)?;
write!(f, " ")?; write!(f, " ")?;
expr.fmt_sse(f)?; expression.fmt_sse(f)?;
write!(f, ")) ")?; write!(f, ")) ")?;
inner.fmt_sse(f)?; inner.fmt_sse(f)?;
write!(f, ")") write!(f, ")")
@ -678,7 +686,7 @@ impl GraphPattern {
} }
Self::Service { Self::Service {
name, name,
pattern, inner,
silent, silent,
} => { } => {
write!(f, "(service ")?; write!(f, "(service ")?;
@ -687,16 +695,16 @@ impl GraphPattern {
} }
name.fmt_sse(f)?; name.fmt_sse(f)?;
write!(f, " ")?; write!(f, " ")?;
pattern.fmt_sse(f)?; inner.fmt_sse(f)?;
write!(f, ")") write!(f, ")")
} }
Self::Group { Self::Group {
inner, inner,
by, variables,
aggregates, aggregates,
} => { } => {
write!(f, "(group (")?; write!(f, "(group (")?;
for (i, v) in by.iter().enumerate() { for (i, v) in variables.iter().enumerate() {
if i > 0 { if i > 0 {
write!(f, " ")?; write!(f, " ")?;
} }
@ -717,14 +725,17 @@ impl GraphPattern {
inner.fmt_sse(f)?; inner.fmt_sse(f)?;
write!(f, ")") write!(f, ")")
} }
Self::Table { variables, rows } => { Self::Values {
variables,
bindings,
} => {
write!(f, "(table (vars")?; write!(f, "(table (vars")?;
for var in variables { for var in variables {
write!(f, " ")?; write!(f, " ")?;
var.fmt_sse(f)?; var.fmt_sse(f)?;
} }
write!(f, ")")?; write!(f, ")")?;
for row in rows { for row in bindings {
write!(f, " (row")?; write!(f, " (row")?;
for (value, var) in row.iter().zip(variables) { for (value, var) in row.iter().zip(variables) {
if let Some(value) = value { if let Some(value) = value {
@ -739,9 +750,9 @@ impl GraphPattern {
} }
write!(f, ")") write!(f, ")")
} }
Self::OrderBy { inner, condition } => { Self::OrderBy { inner, expression } => {
write!(f, "(order (")?; write!(f, "(order (")?;
for (i, c) in condition.iter().enumerate() { for (i, c) in expression.iter().enumerate() {
if i > 0 { if i > 0 {
write!(f, " ")?; write!(f, " ")?;
} }
@ -751,9 +762,9 @@ impl GraphPattern {
inner.fmt_sse(f)?; inner.fmt_sse(f)?;
write!(f, ")") write!(f, ")")
} }
Self::Project { inner, projection } => { Self::Project { inner, variables } => {
write!(f, "(project (")?; write!(f, "(project (")?;
for (i, v) in projection.iter().enumerate() { for (i, v) in variables.iter().enumerate() {
if i > 0 { if i > 0 {
write!(f, " ")?; write!(f, " ")?;
} }
@ -793,8 +804,8 @@ impl GraphPattern {
impl fmt::Display for GraphPattern { impl fmt::Display for GraphPattern {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
Self::Bgp(p) => { Self::Bgp { patterns } => {
for pattern in p { for pattern in patterns {
write!(f, "{} .", pattern)? write!(f, "{} .", pattern)?
} }
Ok(()) Ok(())
@ -824,8 +835,12 @@ impl fmt::Display for GraphPattern {
write!(f, "{} {}", left, right) write!(f, "{} {}", left, right)
} }
} }
Self::LeftJoin { left, right, expr } => { Self::LeftJoin {
if let Some(expr) = expr { left,
right,
expression,
} => {
if let Some(expr) = expression {
write!(f, "{} OPTIONAL {{ {} FILTER({}) }}", left, right, expr) write!(f, "{} OPTIONAL {{ {} FILTER({}) }}", left, right, expr)
} else { } else {
write!(f, "{} OPTIONAL {{ {} }}", left, right) write!(f, "{} OPTIONAL {{ {} }}", left, right)
@ -835,29 +850,36 @@ impl fmt::Display for GraphPattern {
write!(f, "{} FILTER({})", inner, expr) write!(f, "{} FILTER({})", inner, expr)
} }
Self::Union { left, right } => write!(f, "{{ {} }} UNION {{ {} }}", left, right,), Self::Union { left, right } => write!(f, "{{ {} }} UNION {{ {} }}", left, right,),
Self::Graph { graph_name, inner } => { Self::Graph { name, inner } => {
write!(f, "GRAPH {} {{ {} }}", 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::Minus { left, right } => write!(f, "{} MINUS {{ {} }}", left, right),
Self::Service { Self::Service {
name, name,
pattern, inner,
silent, silent,
} => { } => {
if *silent { if *silent {
write!(f, "SERVICE SILENT {} {{ {} }}", name, pattern) write!(f, "SERVICE SILENT {} {{ {} }}", name, inner)
} else { } else {
write!(f, "SERVICE {} {{ {} }}", name, pattern) write!(f, "SERVICE {} {{ {} }}", name, inner)
} }
} }
Self::Table { variables, rows } => { Self::Values {
variables,
bindings,
} => {
write!(f, "VALUES ( ")?; write!(f, "VALUES ( ")?;
for var in variables { for var in variables {
write!(f, "{} ", var)?; write!(f, "{} ", var)?;
} }
write!(f, ") {{ ")?; write!(f, ") {{ ")?;
for row in rows { for row in bindings {
write!(f, "( ")?; write!(f, "( ")?;
for val in row { for val in row {
match val { match val {
@ -871,20 +893,20 @@ impl fmt::Display for GraphPattern {
} }
Self::Group { Self::Group {
inner, inner,
by, variables,
aggregates, aggregates,
} => { } => {
write!(f, "{{SELECT")?; write!(f, "{{SELECT")?;
for (a, v) in aggregates { for (a, v) in aggregates {
write!(f, " ({} AS {})", v, a)?; write!(f, " ({} AS {})", v, a)?;
} }
for b in by { for b in variables {
write!(f, " {}", b)?; write!(f, " {}", b)?;
} }
write!(f, " WHERE {{ {} }}", inner)?; write!(f, " WHERE {{ {} }}", inner)?;
if !by.is_empty() { if !variables.is_empty() {
write!(f, " GROUP BY")?; write!(f, " GROUP BY")?;
for v in by { for v in variables {
write!(f, " {}", v)?; write!(f, " {}", v)?;
} }
} }
@ -904,7 +926,9 @@ impl fmt::Display for GraphPattern {
impl Default for GraphPattern { impl Default for GraphPattern {
fn default() -> Self { 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)) { fn lookup_in_scope_variables<'a>(&'a self, callback: &mut impl FnMut(&'a Variable)) {
match self { match self {
Self::Bgp(p) => { Self::Bgp { patterns } => {
for pattern in p { for pattern in patterns {
lookup_triple_pattern_variables(pattern, callback) lookup_triple_pattern_variables(pattern, callback)
} }
} }
@ -950,33 +974,39 @@ impl GraphPattern {
left.lookup_in_scope_variables(callback); left.lookup_in_scope_variables(callback);
right.lookup_in_scope_variables(callback); right.lookup_in_scope_variables(callback);
} }
Self::Graph { graph_name, inner } => { Self::Graph { name, inner } => {
if let NamedNodePattern::Variable(ref g) = graph_name { if let NamedNodePattern::Variable(ref g) = name {
callback(g); callback(g);
} }
inner.lookup_in_scope_variables(callback); inner.lookup_in_scope_variables(callback);
} }
Self::Extend { inner, var, .. } => { Self::Extend {
callback(var); inner, variable, ..
} => {
callback(variable);
inner.lookup_in_scope_variables(callback); inner.lookup_in_scope_variables(callback);
} }
Self::Minus { left, .. } => left.lookup_in_scope_variables(callback), Self::Minus { left, .. } => left.lookup_in_scope_variables(callback),
Self::Service { pattern, .. } => pattern.lookup_in_scope_variables(callback), Self::Service { inner, .. } => inner.lookup_in_scope_variables(callback),
Self::Group { by, aggregates, .. } => { Self::Group {
for v in by { variables,
aggregates,
..
} => {
for v in variables {
callback(v); callback(v);
} }
for (v, _) in aggregates { for (v, _) in aggregates {
callback(v); callback(v);
} }
} }
Self::Table { variables, .. } => { Self::Values { variables, .. } => {
for v in variables { for v in variables {
callback(v); callback(v);
} }
} }
Self::Project { projection, .. } => { Self::Project { variables, .. } => {
for v in projection { for v in variables {
callback(v); callback(v);
} }
} }
@ -1029,12 +1059,12 @@ impl<'a> fmt::Display for SparqlGraphRootPattern<'a> {
let mut child = self.pattern; let mut child = self.pattern;
loop { loop {
match child { match child {
GraphPattern::OrderBy { inner, condition } => { GraphPattern::OrderBy { inner, expression } => {
order = Some(condition); order = Some(expression);
child = &*inner; child = &*inner;
} }
GraphPattern::Project { inner, projection } if project.is_empty() => { GraphPattern::Project { inner, variables } if project.is_empty() => {
project = projection; project = variables;
child = &*inner; child = &*inner;
} }
GraphPattern::Distinct { 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`]) /// A set function used in aggregates (c.f. [`GraphPattern::Group`])
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum AggregationFunction { pub enum AggregateExpression {
/// [Count](https://www.w3.org/TR/sparql11-query/#defn_aggCount) /// [Count](https://www.w3.org/TR/sparql11-query/#defn_aggCount)
Count { Count {
expr: Option<Box<Expression>>, expr: Option<Box<Expression>>,
@ -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). /// 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 { pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
match self { 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 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
Self::Count { expr, distinct } => { Self::Count { expr, distinct } => {
@ -1317,14 +1347,14 @@ impl fmt::Display for AggregationFunction {
/// An ordering comparator used by [`GraphPattern::OrderBy`] /// An ordering comparator used by [`GraphPattern::OrderBy`]
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum OrderComparator { pub enum OrderExpression {
/// Ascending order /// Ascending order
Asc(Expression), Asc(Expression),
/// Descending order /// Descending order
Desc(Expression), Desc(Expression),
} }
impl OrderComparator { impl OrderExpression {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html). /// 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 { pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
match self { 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 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
Self::Asc(e) => write!(f, "ASC({})", e), Self::Asc(e) => write!(f, "ASC({})", e),

@ -262,7 +262,9 @@ fn build_bgp(patterns: Vec<TripleOrPathPattern>) -> GraphPattern {
object, object,
} => { } => {
if !bgp.is_empty() { if !bgp.is_empty() {
elements.push(GraphPattern::Bgp(take(&mut bgp))); elements.push(GraphPattern::Bgp {
patterns: take(&mut bgp),
});
} }
elements.push(GraphPattern::Path { elements.push(GraphPattern::Path {
subject, subject,
@ -273,7 +275,7 @@ fn build_bgp(patterns: Vec<TripleOrPathPattern>) -> GraphPattern {
} }
} }
if !bgp.is_empty() { if !bgp.is_empty() {
elements.push(GraphPattern::Bgp(bgp)); elements.push(GraphPattern::Bgp { patterns: bgp });
} }
new_sequence(elements) new_sequence(elements)
} }
@ -355,12 +357,12 @@ enum PartialGraphPattern {
fn new_join(l: GraphPattern, r: GraphPattern) -> GraphPattern { fn new_join(l: GraphPattern, r: GraphPattern) -> GraphPattern {
//Avoid to output empty BGPs //Avoid to output empty BGPs
if let GraphPattern::Bgp(pl) = &l { if let GraphPattern::Bgp { patterns: pl } = &l {
if pl.is_empty() { if pl.is_empty() {
return r; return r;
} }
} }
if let GraphPattern::Bgp(pr) = &r { if let GraphPattern::Bgp { patterns: pr } = &r {
if pr.is_empty() { if pr.is_empty() {
return l; return l;
} }
@ -369,39 +371,33 @@ fn new_join(l: GraphPattern, r: GraphPattern) -> GraphPattern {
// Some optimizations // Some optimizations
// TODO: move to a specific optimizer pass // TODO: move to a specific optimizer pass
match (l, r) { match (l, r) {
(GraphPattern::Bgp(mut pl), GraphPattern::Bgp(pr)) => { (GraphPattern::Bgp { patterns: mut pl }, GraphPattern::Bgp { patterns: pr }) => {
pl.extend(pr); pl.extend(pr);
GraphPattern::Bgp(pl) GraphPattern::Bgp { patterns: pl }
} }
(GraphPattern::Sequence(mut e1), GraphPattern::Sequence(e2)) => { (GraphPattern::Sequence(mut e1), GraphPattern::Sequence(e2)) => {
e1.extend_from_slice(&e2); e1.extend_from_slice(&e2);
GraphPattern::Sequence(e1) GraphPattern::Sequence(e1)
} }
(GraphPattern::Sequence(mut e), r) (GraphPattern::Sequence(mut e), r)
if matches!(r, GraphPattern::Bgp(_) | GraphPattern::Path { .. }) => if matches!(r, GraphPattern::Bgp { .. } | GraphPattern::Path { .. }) =>
{ {
e.push(r); e.push(r);
GraphPattern::Sequence(e) GraphPattern::Sequence(e)
} }
(l, GraphPattern::Sequence(mut e)) (l, GraphPattern::Sequence(mut e))
if matches!(l, GraphPattern::Bgp(_) | GraphPattern::Path { .. }) => if matches!(l, GraphPattern::Bgp { .. } | GraphPattern::Path { .. }) =>
{ {
e.insert(0, l); e.insert(0, l);
GraphPattern::Sequence(e) GraphPattern::Sequence(e)
} }
( (
GraphPattern::Graph { GraphPattern::Graph { name: g1, inner: l },
graph_name: g1, GraphPattern::Graph { name: g2, inner: r },
inner: l,
},
GraphPattern::Graph {
graph_name: g2,
inner: r,
},
) if g1 == g2 => { ) if g1 == g2 => {
// We merge identical graphs // We merge identical graphs
GraphPattern::Graph { GraphPattern::Graph {
graph_name: g1, name: g1,
inner: Box::new(new_join(*l, *r)), 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>) -> GraphPattern { fn new_sequence(elements: Vec<GraphPattern>) -> GraphPattern {
match elements.len() { match elements.len() {
0 => GraphPattern::Bgp(vec![]), 0 => GraphPattern::default(),
1 => elements.into_iter().next().unwrap(), 1 => elements.into_iter().next().unwrap(),
_ => GraphPattern::Sequence(elements), _ => GraphPattern::Sequence(elements),
} }
@ -467,7 +463,7 @@ fn build_select(
wher: GraphPattern, wher: GraphPattern,
mut group: Option<(Vec<Variable>, Vec<(Expression, Variable)>)>, mut group: Option<(Vec<Variable>, Vec<(Expression, Variable)>)>,
having: Option<Expression>, having: Option<Expression>,
order_by: Option<Vec<OrderComparator>>, order_by: Option<Vec<OrderExpression>>,
offset_limit: Option<(usize, Option<usize>)>, offset_limit: Option<(usize, Option<usize>)>,
values: Option<GraphPattern>, values: Option<GraphPattern>,
state: &mut ParserState, state: &mut ParserState,
@ -482,16 +478,16 @@ fn build_select(
} }
if let Some((clauses, binds)) = group { if let Some((clauses, binds)) = group {
for (expr, var) in binds { for (expression, variable) in binds {
p = GraphPattern::Extend { p = GraphPattern::Extend {
inner: Box::new(p), inner: Box::new(p),
var, variable,
expr, expression,
}; };
} }
p = GraphPattern::Group { p = GraphPattern::Group {
inner: Box::new(p), inner: Box::new(p),
by: clauses, variables: clauses,
aggregates, aggregates,
}; };
with_aggregate = true; with_aggregate = true;
@ -527,14 +523,14 @@ fn build_select(
} }
v v
} }
SelectionMember::Expression(expr, v) => { SelectionMember::Expression(expression, variable) => {
if visible.contains(&v) { if visible.contains(&variable) {
// We disallow to override an existing variable with an expression // We disallow to override an existing variable with an expression
return Err( return Err(
"The SELECT overrides an existing variable using an expression", "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 // We validate projection variables if there is an aggregate
return Err( return Err(
"The SELECT contains an exprssion with a variable that is unbound", "The SELECT contains an exprssion with a variable that is unbound",
@ -542,10 +538,10 @@ fn build_select(
} }
p = GraphPattern::Extend { p = GraphPattern::Extend {
inner: Box::new(p), inner: Box::new(p),
var: v.clone(), variable: variable.clone(),
expr, expression,
}; };
v variable
} }
}; };
if pv.contains(&v) { if pv.contains(&v) {
@ -574,10 +570,10 @@ fn build_select(
let mut m = p; let mut m = p;
//ORDER BY //ORDER BY
if let Some(condition) = order_by { if let Some(expression) = order_by {
m = GraphPattern::OrderBy { m = GraphPattern::OrderBy {
inner: Box::new(m), inner: Box::new(m),
condition, expression,
}; };
} }
@ -585,7 +581,7 @@ fn build_select(
if with_project { if with_project {
m = GraphPattern::Project { m = GraphPattern::Project {
inner: Box::new(m), inner: Box::new(m),
projection: pv, variables: pv,
}; };
} }
match select.option { match select.option {
@ -645,11 +641,13 @@ fn are_variables_bound(expression: &Expression, variables: &HashSet<Variable>) -
} }
fn copy_graph(from: impl Into<GraphName>, to: impl Into<GraphNamePattern>) -> GraphUpdateOperation { fn copy_graph(from: impl Into<GraphName>, to: impl Into<GraphNamePattern>) -> GraphUpdateOperation {
let bgp = GraphPattern::Bgp(vec![TriplePattern::new( let bgp = GraphPattern::Bgp {
Variable { name: "s".into() }, patterns: vec![TriplePattern::new(
Variable { name: "p".into() }, Variable { name: "s".into() },
Variable { name: "o".into() }, Variable { name: "p".into() },
)]); Variable { name: "o".into() },
)],
};
GraphUpdateOperation::DeleteInsert { GraphUpdateOperation::DeleteInsert {
delete: Vec::new(), delete: Vec::new(),
insert: vec![QuadPattern::new( insert: vec![QuadPattern::new(
@ -661,7 +659,7 @@ fn copy_graph(from: impl Into<GraphName>, to: impl Into<GraphNamePattern>) -> Gr
using: None, using: None,
pattern: Box::new(match from.into() { pattern: Box::new(match from.into() {
GraphName::NamedNode(from) => GraphPattern::Graph { GraphName::NamedNode(from) => GraphPattern::Graph {
graph_name: from.into(), name: from.into(),
inner: Box::new(bgp), inner: Box::new(bgp),
}, },
GraphName::DefaultGraph => bgp, GraphName::DefaultGraph => bgp,
@ -679,7 +677,7 @@ pub struct ParserState {
namespaces: HashMap<String, String>, namespaces: HashMap<String, String>,
used_bnodes: HashSet<BlankNode>, used_bnodes: HashSet<BlankNode>,
currently_used_bnodes: HashSet<BlankNode>, currently_used_bnodes: HashSet<BlankNode>,
aggregates: Vec<Vec<(Variable, AggregationFunction)>>, aggregates: Vec<Vec<(Variable, AggregateExpression)>>,
} }
impl ParserState { impl ParserState {
@ -691,7 +689,7 @@ impl ParserState {
} }
} }
fn new_aggregation(&mut self, agg: AggregationFunction) -> Result<Variable, &'static str> { fn new_aggregation(&mut self, agg: AggregateExpression) -> Result<Variable, &'static str> {
let aggregates = self.aggregates.last_mut().ok_or("Unexpected aggregate")?; let aggregates = self.aggregates.last_mut().ok_or("Unexpected aggregate")?;
Ok(aggregates Ok(aggregates
.iter() .iter()
@ -1003,7 +1001,7 @@ parser! {
dataset: d, dataset: d,
pattern: build_select( pattern: build_select(
Selection::no_op(), Selection::no_op(),
GraphPattern::Bgp(c), GraphPattern::Bgp { patterns: c },
g, h, o, l, v, state g, h, o, l, v, state
)?, )?,
base_iri: state.base_iri.clone() base_iri: state.base_iri.clone()
@ -1117,15 +1115,15 @@ parser! {
rule HavingCondition() -> Expression = Constraint() rule HavingCondition() -> Expression = Constraint()
//[23] //[23]
rule OrderClause() -> Vec<OrderComparator> = i("ORDER") _ i("BY") _ c:OrderClause_item()+ { c } rule OrderClause() -> Vec<OrderExpression> = i("ORDER") _ i("BY") _ c:OrderClause_item()+ { c }
rule OrderClause_item() -> OrderComparator = c:OrderCondition() _ { c } rule OrderClause_item() -> OrderExpression = c:OrderCondition() _ { c }
//[24] //[24]
rule OrderCondition() -> OrderComparator = rule OrderCondition() -> OrderExpression =
i("ASC") _ e: BrackettedExpression() { OrderComparator::Asc(e) } / i("ASC") _ e: BrackettedExpression() { OrderExpression::Asc(e) } /
i("DESC") _ e: BrackettedExpression() { OrderComparator::Desc(e) } / i("DESC") _ e: BrackettedExpression() { OrderExpression::Desc(e) } /
e: Constraint() { OrderComparator::Asc(e) } / e: Constraint() { OrderExpression::Asc(e) } /
v: Var() { OrderComparator::Asc(Expression::from(v)) } v: Var() { OrderExpression::Asc(Expression::from(v)) }
//[25] //[25]
rule LimitOffsetClauses() -> (usize, Option<usize>) = rule LimitOffsetClauses() -> (usize, Option<usize>) =
@ -1156,8 +1154,8 @@ parser! {
rule Update1_silent() -> bool = i("SILENT") { true } / { false } rule Update1_silent() -> bool = i("SILENT") { true } / { false }
//[31] //[31]
rule Load() -> Vec<GraphUpdateOperation> = i("LOAD") _ silent:Update1_silent() _ from:iri() _ to:Load_to()? { rule Load() -> Vec<GraphUpdateOperation> = i("LOAD") _ silent:Update1_silent() _ source:iri() _ destination:Load_to()? {
vec![GraphUpdateOperation::Load { silent, from, to: to.map_or(GraphName::DefaultGraph, GraphName::NamedNode) }] vec![GraphUpdateOperation::Load { silent, source, destination: destination.map_or(GraphName::DefaultGraph, GraphName::NamedNode) }]
} }
rule Load_to() -> NamedNode = i("INTO") _ g: GraphRef() { g } rule Load_to() -> NamedNode = i("INTO") _ g: GraphRef() { g }
@ -1182,7 +1180,7 @@ parser! {
if from == to { if from == to {
Vec::new() // identity case Vec::new() // identity case
} else { } else {
let bgp = GraphPattern::Bgp(vec![TriplePattern::new(Variable { 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)] vec![copy_graph(from, to)]
} }
} }
@ -1193,7 +1191,7 @@ parser! {
if from == to { if from == to {
Vec::new() // identity case Vec::new() // identity case
} else { } else {
let bgp = GraphPattern::Bgp(vec![TriplePattern::new(Variable { 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() }] 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 { if from == to {
Vec::new() // identity case Vec::new() // identity case
} else { } 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)] vec![GraphUpdateOperation::Drop { silent: true, graph: to.clone().into() }, copy_graph(from, to)]
} }
} }
@ -1222,11 +1220,11 @@ parser! {
//[40] //[40]
rule DeleteWhere() -> Vec<GraphUpdateOperation> = i("DELETE") _ i("WHERE") _ d:QuadPattern() {? rule DeleteWhere() -> Vec<GraphUpdateOperation> = i("DELETE") _ i("WHERE") _ d:QuadPattern() {?
let pattern = new_sequence(d.iter().map(|q| { 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 { 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::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()); }).collect());
let delete = d.into_iter().map(GroundQuadPattern::try_from).collect::<Result<Vec<_>,_>>().map_err(|_| "Blank nodes are not allowed in DELETE WHERE")?; let delete = d.into_iter().map(GroundQuadPattern::try_from).collect::<Result<Vec<_>,_>>().map_err(|_| "Blank nodes are not allowed in DELETE WHERE")?;
@ -1393,22 +1391,22 @@ parser! {
for e in b.into_iter().flatten() { for e in b.into_iter().flatten() {
match e { match e {
PartialGraphPattern::Optional(p, f) => { 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) => { PartialGraphPattern::Minus(p) => {
g = GraphPattern::Minus { left: Box::new(g), right: Box::new(p) } g = GraphPattern::Minus { left: Box::new(g), right: Box::new(p) }
} }
PartialGraphPattern::Bind(expr, var) => { PartialGraphPattern::Bind(expression, variable) => {
let mut contains = false; let mut contains = false;
g.on_in_scope_variable(|v| { g.on_in_scope_variable(|v| {
if *v == var { if *v == variable {
contains = true; contains = true;
} }
}); });
if contains { if contains {
return Err("BIND is overriding an existing variable") 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 { PartialGraphPattern::Filter(expr) => filter = Some(if let Some(f) = filter {
Expression::And(Box::new(f), Box::new(expr)) Expression::And(Box::new(f), Box::new(expr))
@ -1458,14 +1456,14 @@ parser! {
} }
//[58] //[58]
rule GraphGraphPattern() -> PartialGraphPattern = i("GRAPH") _ graph_name:VarOrIri() _ p:GroupGraphPattern() { rule GraphGraphPattern() -> PartialGraphPattern = i("GRAPH") _ name:VarOrIri() _ p:GroupGraphPattern() {
PartialGraphPattern::Other(GraphPattern::Graph { graph_name, inner: Box::new(p) }) PartialGraphPattern::Other(GraphPattern::Graph { name, inner: Box::new(p) })
} }
//[59] //[59]
rule ServiceGraphPattern() -> PartialGraphPattern = rule ServiceGraphPattern() -> PartialGraphPattern =
i("SERVICE") _ i("SILENT") _ 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, pattern: Box::new(p), silent: true }) } i("SERVICE") _ name:VarOrIri() _ p:GroupGraphPattern() { PartialGraphPattern::Other(GraphPattern::Service{ name, inner: Box::new(p), silent: true }) }
//[60] //[60]
rule Bind() -> PartialGraphPattern = i("BIND") _ "(" _ e:Expression() _ i("AS") _ v:Var() _ ")" { rule Bind() -> PartialGraphPattern = i("BIND") _ "(" _ e:Expression() _ i("AS") _ v:Var() _ ")" {
@ -1477,7 +1475,7 @@ parser! {
//[62] //[62]
rule DataBlock() -> GraphPattern = l:(InlineDataOneVar() / InlineDataFull()) { rule DataBlock() -> GraphPattern = l:(InlineDataOneVar() / InlineDataFull()) {
GraphPattern::Table { variables: l.0, rows: l.1 } GraphPattern::Values { variables: l.0, bindings: l.1 }
} }
//[63] //[63]
@ -2085,27 +2083,27 @@ parser! {
rule NotExistsFunc() -> Expression = i("NOT") _ i("EXISTS") _ p:GroupGraphPattern() { Expression::Not(Box::new(Expression::Exists(Box::new(p)))) } rule NotExistsFunc() -> Expression = i("NOT") _ i("EXISTS") _ p:GroupGraphPattern() { Expression::Not(Box::new(Expression::Exists(Box::new(p)))) }
//[127] //[127]
rule Aggregate() -> AggregationFunction = rule Aggregate() -> AggregateExpression =
i("COUNT") _ "(" _ i("DISTINCT") _ "*" _ ")" { AggregationFunction::Count { expr: None, distinct: true } } / i("COUNT") _ "(" _ i("DISTINCT") _ "*" _ ")" { AggregateExpression::Count { expr: None, distinct: true } } /
i("COUNT") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregationFunction::Count { expr: Some(Box::new(e)), distinct: true } } / i("COUNT") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregateExpression::Count { expr: Some(Box::new(e)), distinct: true } } /
i("COUNT") _ "(" _ "*" _ ")" { AggregationFunction::Count { expr: None, distinct: false } } / i("COUNT") _ "(" _ "*" _ ")" { AggregateExpression::Count { expr: None, distinct: false } } /
i("COUNT") _ "(" _ e:Expression() _ ")" { AggregationFunction::Count { expr: Some(Box::new(e)), distinct: false } } / i("COUNT") _ "(" _ e:Expression() _ ")" { AggregateExpression::Count { expr: Some(Box::new(e)), distinct: false } } /
i("SUM") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregationFunction::Sum { expr: Box::new(e), distinct: true } } / i("SUM") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregateExpression::Sum { expr: Box::new(e), distinct: true } } /
i("SUM") _ "(" _ e:Expression() _ ")" { AggregationFunction::Sum { expr: Box::new(e), distinct: false } } / i("SUM") _ "(" _ e:Expression() _ ")" { AggregateExpression::Sum { expr: Box::new(e), distinct: false } } /
i("MIN") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregationFunction::Min { expr: Box::new(e), distinct: true } } / i("MIN") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregateExpression::Min { expr: Box::new(e), distinct: true } } /
i("MIN") _ "(" _ e:Expression() _ ")" { AggregationFunction::Min { expr: Box::new(e), distinct: false } } / i("MIN") _ "(" _ e:Expression() _ ")" { AggregateExpression::Min { expr: Box::new(e), distinct: false } } /
i("MAX") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregationFunction::Max { expr: Box::new(e), distinct: true } } / i("MAX") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregateExpression::Max { expr: Box::new(e), distinct: true } } /
i("MAX") _ "(" _ e:Expression() _ ")" { AggregationFunction::Max { expr: Box::new(e), distinct: false } } / i("MAX") _ "(" _ e:Expression() _ ")" { AggregateExpression::Max { expr: Box::new(e), distinct: false } } /
i("AVG") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregationFunction::Avg { expr: Box::new(e), distinct: true } } / i("AVG") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregateExpression::Avg { expr: Box::new(e), distinct: true } } /
i("AVG") _ "(" _ e:Expression() _ ")" { AggregationFunction::Avg { expr: Box::new(e), distinct: false } } / i("AVG") _ "(" _ e:Expression() _ ")" { AggregateExpression::Avg { expr: Box::new(e), distinct: false } } /
i("SAMPLE") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregationFunction::Sample { expr: Box::new(e), distinct: true } } / i("SAMPLE") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregateExpression::Sample { expr: Box::new(e), distinct: true } } /
i("SAMPLE") _ "(" _ e:Expression() _ ")" { AggregationFunction::Sample { expr: Box::new(e), distinct: false } } / i("SAMPLE") _ "(" _ e:Expression() _ ")" { AggregateExpression::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() _ ";" _ i("SEPARATOR") _ "=" _ s:String() _ ")" { AggregateExpression::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") _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregateExpression::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() _ ";" _ i("SEPARATOR") _ "=" _ s:String() _ ")" { AggregateExpression::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 } } / i("GROUP_CONCAT") _ "(" _ e:Expression() _ ")" { AggregateExpression::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() _ "(" _ i("DISTINCT") _ e:Expression() _ ")" { AggregateExpression::Custom { name, expr: Box::new(e), distinct: true } } /
name:iri() _ "(" _ e:Expression() _ ")" { AggregationFunction::Custom { name, expr: Box::new(e), distinct: false } } name:iri() _ "(" _ e:Expression() _ ")" { AggregateExpression::Custom { name, expr: Box::new(e), distinct: false } }
//[128] //[128]
rule iriOrFunction() -> Expression = i: iri() _ a: ArgList()? { rule iriOrFunction() -> Expression = i: iri() _ a: ArgList()? {

@ -110,8 +110,8 @@ pub enum GraphUpdateOperation {
/// [load](https://www.w3.org/TR/sparql11-update/#defn_loadOperation) /// [load](https://www.w3.org/TR/sparql11-update/#defn_loadOperation)
Load { Load {
silent: bool, silent: bool,
from: NamedNode, source: NamedNode,
to: GraphName, destination: GraphName,
}, },
/// [clear](https://www.w3.org/TR/sparql11-update/#defn_clearOperation) /// [clear](https://www.w3.org/TR/sparql11-update/#defn_clearOperation)
Clear { silent: bool, graph: GraphTarget }, Clear { silent: bool, graph: GraphTarget },
@ -183,14 +183,18 @@ impl GraphUpdateOperation {
} }
write!(f, ")") write!(f, ")")
} }
GraphUpdateOperation::Load { silent, from, to } => { GraphUpdateOperation::Load {
silent,
source,
destination,
} => {
write!(f, "(load ")?; write!(f, "(load ")?;
if *silent { if *silent {
write!(f, "silent ")?; write!(f, "silent ")?;
} }
from.fmt_sse(f)?; source.fmt_sse(f)?;
write!(f, " ")?; write!(f, " ")?;
to.fmt_sse(f)?; destination.fmt_sse(f)?;
write!(f, ")") write!(f, ")")
} }
GraphUpdateOperation::Clear { silent, graph } => { 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 ")?; write!(f, "LOAD ")?;
if *silent { if *silent {
write!(f, "SILENT ")?; write!(f, "SILENT ")?;
} }
write!(f, "{}", from)?; write!(f, "{}", source)?;
if to != &GraphName::DefaultGraph { if destination != &GraphName::DefaultGraph {
write!(f, " INTO GRAPH {}", to)?; write!(f, " INTO GRAPH {}", destination)?;
} }
Ok(()) Ok(())
} }

Loading…
Cancel
Save