Adds OX_LATERAL OPTIONAL and OX_LATERAL GRAPH

lateral
Tpt 2 years ago
parent e922d3293b
commit add1dff458
  1. 23
      lib/spargebra/src/algebra.rs
  2. 31
      lib/spargebra/src/parser.rs
  3. 5
      lib/src/sparql/plan_builder.rs
  4. 6
      testsuite/oxigraph-tests/sparql/lateral/graph.rq
  5. 12
      testsuite/oxigraph-tests/sparql/lateral/manifest.ttl
  6. 6
      testsuite/oxigraph-tests/sparql/lateral/optional.rq
  7. 17
      testsuite/oxigraph-tests/sparql/lateral/simple.srx

@ -529,6 +529,8 @@ pub enum GraphPattern {
right: Box<Self>,
expression: Option<Expression>,
},
/// Executes the left child and for each result tuple left join with right by injecting tuple to right
LeftSequence { left: Box<Self>, right: Box<Self> },
/// [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).
@ -625,6 +627,13 @@ impl GraphPattern {
right.fmt_sse(f)?;
write!(f, ")")
}
Self::LeftSequence { left, right } => {
write!(f, "(leftsequence ")?;
left.fmt_sse(f)?;
write!(f, " ")?;
right.fmt_sse(f)?;
write!(f, ")")
}
Self::LeftJoin {
left,
right,
@ -846,8 +855,19 @@ impl fmt::Display for GraphPattern {
}
}
Self::Sequence { left, right } => {
write!(f, "{} {}", left, right)
if cfg!(feature = "ex_lateral") && matches!(right.as_ref(), Self::Graph { .. }) {
// The second block might be considered as a modification of the first one.
write!(f, "{} OX_LATERAL {}", left, right)
} else {
write!(f, "{} {}", left, right)
}
}
#[cfg(feature = "ex-lateral")]
Self::LeftSequence { left, right } => {
write!(f, "{} OX_LATERAL OPTIONAL {{ {} }}", left, right)
}
#[cfg(not(feature = "ex-lateral"))]
Self::LeftSequence { .. } => Err(fmt::Error),
Self::LeftJoin {
left,
right,
@ -978,6 +998,7 @@ impl GraphPattern {
}
Self::Join { left, right }
| Self::Sequence { left, right }
| Self::LeftSequence { left, right }
| Self::LeftJoin { left, right, .. }
| Self::Union { left, right } => {
left.lookup_in_scope_variables(callback);

@ -363,9 +363,11 @@ enum PartialGraphPattern {
Minus(GraphPattern),
Bind(Expression, Variable),
Filter(Expression),
#[cfg(feature = "ex-lateral")]
Lateral(GraphPattern, Vec<Variable>),
Other(GraphPattern),
#[cfg(feature = "ex-lateral")]
LateralOptional(GraphPattern),
#[cfg(feature = "ex-lateral")]
Lateral(GraphPattern),
}
fn new_join(l: GraphPattern, r: GraphPattern) -> GraphPattern {
@ -1423,10 +1425,12 @@ parser! {
} else {
expr
}),
#[cfg(feature = "ex-lateral")]
PartialGraphPattern::Lateral(p, mut variables) =>
g = new_sequence(g, insert_lateral_variables(p, variables)?),
PartialGraphPattern::Other(e) => g = new_join(g, e),
#[cfg(feature = "ex-lateral")]
PartialGraphPattern::LateralOptional(p) =>
g = GraphPattern::LeftSequence { left: Box::new(g), right: Box::new(p) },
#[cfg(feature = "ex-lateral")]
PartialGraphPattern::Lateral(p) => g = new_sequence(g, p),
}
}
@ -1453,10 +1457,19 @@ parser! {
//[56]
rule GraphPatternNotTriples() -> PartialGraphPattern = GroupOrUnionGraphPattern() / OptionalGraphPattern() / MinusGraphPattern() / GraphGraphPattern() / ServiceGraphPattern() / Filter() / Bind() / InlineData() / OxLateral()
rule OxLateral() -> PartialGraphPattern = i("OX_LATERAL") _ "(" _ vs:OxLateral_variable()* _ ")" _ "{" _ s:SubSelect() _ "}" {?
#[cfg(feature = "ex-lateral")]{ Ok(PartialGraphPattern::Lateral(s, vs)) }
#[cfg(not(feature = "ex-lateral"))]{ Err("The 'OX_LATERAL' syntax is not enabled") }
}
rule OxLateral() -> PartialGraphPattern =
i("OX_LATERAL") _ i("OPTIONAL") _ p:GroupGraphPattern() {?
#[cfg(feature = "ex-lateral")]{ Ok(PartialGraphPattern::LateralOptional(p)) }
#[cfg(not(feature = "ex-lateral"))]{ Err("The 'OX_LATERAL' syntax is not enabled") }
} /
i("OX_LATERAL") _ i("GRAPH") _ name:VarOrIri() _ p:GroupGraphPattern() {?
#[cfg(feature = "ex-lateral")]{ Ok(PartialGraphPattern::Lateral(GraphPattern::Graph { name, inner: Box::new(p) })) }
#[cfg(not(feature = "ex-lateral"))]{ Err("The 'OX_LATERAL' syntax is not enabled") }
} /
i("OX_LATERAL") _ "(" _ vs:OxLateral_variable()* _ ")" _ "{" _ s:SubSelect() _ "}" {?
#[cfg(feature = "ex-lateral")]{ Ok(PartialGraphPattern::Lateral(insert_lateral_variables(s, vs)?)) }
#[cfg(not(feature = "ex-lateral"))]{ Err("The 'OX_LATERAL' syntax is not enabled") }
}
rule OxLateral_variable() -> Variable = v:Var() _ {
v
}

@ -97,6 +97,11 @@ impl<'a> PlanBuilder<'a> {
left: Box::new(self.build_for_graph_pattern(left, variables, graph_name)?),
right: Box::new(self.build_for_graph_pattern(right, variables, graph_name)?),
},
GraphPattern::LeftSequence { left, right } => PlanNode::LeftJoin {
left: Box::new(self.build_for_graph_pattern(left, variables, graph_name)?),
right: Box::new(self.build_for_graph_pattern(right, variables, graph_name)?),
possible_problem_vars: Rc::new(Vec::new()),
},
GraphPattern::LeftJoin {
left,
right,

@ -0,0 +1,6 @@
PREFIX ex: <http://example.org/>
SELECT ?s ?o WHERE {
VALUES ?s { ex:S }
OX_LATERAL GRAPH ex:G { FILTER(BOUND(?s)) . VALUES ?o { ex:O } }
}

@ -13,6 +13,8 @@
:subselect_inside_optional
:subselect_implicit_aggregate
:subselect_explicit_aggregate
:optional
:graph
) .
:subselect rdf:type mf:QueryEvaluationTest ;
@ -42,3 +44,13 @@
[ qt:query <subselect_explicit_aggregate.rq> ;
qt:data <basic_input.ttl> ] ;
mf:result <subselect_explicit_aggregate.srx> .
:optional rdf:type mf:QueryEvaluationTest ;
mf:name "OX_LATERAL OPTIONAL test" ;
mf:action [ qt:query <optional.rq> ] ;
mf:result <simple.srx> .
:optional rdf:type mf:QueryEvaluationTest ;
mf:name "OX_LATERAL GRAPH test" ;
mf:action [ qt:query <graph.rq> ] ;
mf:result <simple.srx> .

@ -0,0 +1,6 @@
PREFIX ex: <http://example.org/>
SELECT ?s ?o WHERE {
VALUES ?s { ex:S }
OX_LATERAL OPTIONAL { FILTER(BOUND(?s)) . VALUES ?o { ex:O } }
}

@ -0,0 +1,17 @@
<?xml version="1.0"?>
<sparql xmlns="http://www.w3.org/2005/sparql-results#">
<head>
<variable name="s"/>
<variable name="o"/>
</head>
<results>
<result>
<binding name="s">
<uri>http://example.org/S</uri>
</binding>
<binding name="o">
<uri>http://example.org/O</uri>
</binding>
</result>
</results>
</sparql>
Loading…
Cancel
Save