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,
) -> Result<PlanNode, EvaluationError> {
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<Vec<_>, EvaluationError> = condition
GraphPattern::OrderBy { inner, expression } => {
let condition: Result<Vec<_>, 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<PlanNode, EvaluationError> {
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<Variable>,
graph_name: &PatternValue,
) -> Result<PlanAggregation, EvaluationError> {
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",
)),
}

@ -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 {

@ -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<TriplePattern>),
Bgp { patterns: Vec<TriplePattern> },
/// 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<Self>,
right: Box<Self>,
expr: Option<Expression>,
expression: Option<Expression>,
},
/// [Filter](https://www.w3.org/TR/sparql11-query/#defn_algFilter)
Filter { expr: Expression, inner: Box<Self> },
/// [Union](https://www.w3.org/TR/sparql11-query/#defn_algUnion)
Union { left: Box<Self>, right: Box<Self> },
Graph {
graph_name: NamedNodePattern,
name: NamedNodePattern,
inner: Box<Self>,
},
/// [Extend](https://www.w3.org/TR/sparql11-query/#defn_extend)
Extend {
inner: Box<Self>,
var: Variable,
expr: Expression,
variable: Variable,
expression: Expression,
},
/// [Minus](https://www.w3.org/TR/sparql11-query/#defn_algMinus)
Minus { left: Box<Self>, right: Box<Self> },
/// A table used to provide inline values
Table {
Values {
variables: Vec<Variable>,
rows: Vec<Vec<Option<GroundTerm>>>,
bindings: Vec<Vec<Option<GroundTerm>>>,
},
/// [OrderBy](https://www.w3.org/TR/sparql11-query/#defn_algOrdered)
OrderBy {
inner: Box<Self>,
condition: Vec<OrderComparator>,
expression: Vec<OrderExpression>,
},
/// [Project](https://www.w3.org/TR/sparql11-query/#defn_algProjection)
Project {
inner: Box<Self>,
projection: Vec<Variable>,
variables: Vec<Variable>,
},
/// [Distinct](https://www.w3.org/TR/sparql11-query/#defn_algDistinct)
Distinct { inner: Box<Self> },
@ -577,13 +577,13 @@ pub enum GraphPattern {
/// [Group](https://www.w3.org/TR/sparql11-federated-query/#aggregateAlgebra)
Group {
inner: Box<Self>,
by: Vec<Variable>,
aggregates: Vec<(Variable, AggregationFunction)>,
variables: Vec<Variable>,
aggregates: Vec<(Variable, AggregateExpression)>,
},
/// [Service](https://www.w3.org/TR/sparql11-federated-query/#defn_evalService)
Service {
name: NamedNodePattern,
pattern: Box<Self>,
inner: Box<Self>,
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<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).
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),

@ -262,7 +262,9 @@ fn build_bgp(patterns: Vec<TripleOrPathPattern>) -> 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<TripleOrPathPattern>) -> 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>) -> 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<Variable>, Vec<(Expression, Variable)>)>,
having: Option<Expression>,
order_by: Option<Vec<OrderComparator>>,
order_by: Option<Vec<OrderExpression>>,
offset_limit: Option<(usize, Option<usize>)>,
values: Option<GraphPattern>,
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<Variable>) -
}
fn copy_graph(from: impl Into<GraphName>, to: impl Into<GraphNamePattern>) -> 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<GraphName>, to: impl Into<GraphNamePattern>) -> 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<String, String>,
used_bnodes: HashSet<BlankNode>,
currently_used_bnodes: HashSet<BlankNode>,
aggregates: Vec<Vec<(Variable, AggregationFunction)>>,
aggregates: Vec<Vec<(Variable, AggregateExpression)>>,
}
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")?;
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<OrderComparator> = i("ORDER") _ i("BY") _ c:OrderClause_item()+ { c }
rule OrderClause_item() -> OrderComparator = c:OrderCondition() _ { c }
rule OrderClause() -> Vec<OrderExpression> = 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<usize>) =
@ -1156,8 +1154,8 @@ parser! {
rule Update1_silent() -> bool = i("SILENT") { true } / { false }
//[31]
rule Load() -> Vec<GraphUpdateOperation> = 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<GraphUpdateOperation> = 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<GraphUpdateOperation> = 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::<Result<Vec<_>,_>>().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()? {

@ -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(())
}

Loading…
Cancel
Save