Splits GraphPattern in MultiSetPattern and ListPattern

pull/10/head
Tpt 6 years ago
parent 21a4b78105
commit b42428fc86
  1. 157
      src/sparql/algebra.rs
  2. 18
      src/sparql/parser.rs
  3. 62
      src/sparql/sparql_grammar.rustpeg

@ -216,7 +216,7 @@ pub enum Expression {
IsNumericFunctionCall(Box<Expression>),
RegexFunctionCall(Box<Expression>, Box<Expression>, Option<Box<Expression>>),
CustomFunctionCall(NamedNode, Vec<Expression>),
ExistsFunctionCall(Box<GraphPattern>),
ExistsFunctionCall(Box<MultiSetPattern>),
CountAggregate(Option<Box<Expression>>, bool),
SumAggregate(Box<Expression>, bool),
MinAggregate(Box<Expression>, bool),
@ -483,7 +483,7 @@ impl<'a> fmt::Display for SparqlExpression<'a> {
Expression::UnaryMinusExpression(e) => write!(f, "-{}", SparqlExpression(&*e)),
Expression::UnaryNotExpression(e) => match e.as_ref() {
Expression::ExistsFunctionCall(p) => {
write!(f, "NOT EXISTS {{ {} }}", SparqlGraphPattern(&*p))
write!(f, "NOT EXISTS {{ {} }}", SparqlMultiSetPattern(&*p))
}
e => write!(f, "!{}", e),
},
@ -672,7 +672,7 @@ impl<'a> fmt::Display for SparqlExpression<'a> {
.join(", ")
),
Expression::ExistsFunctionCall(p) => {
write!(f, "EXISTS {{ {} }}", SparqlGraphPattern(&*p))
write!(f, "EXISTS {{ {} }}", SparqlMultiSetPattern(&*p))
}
Expression::CountAggregate(e, distinct) => if *distinct {
e.as_ref()
@ -736,30 +736,22 @@ impl<'a> fmt::Display for SparqlExpression<'a> {
}
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)]
pub enum GraphPattern {
Multiset(Vec<Binding>),
pub enum MultiSetPattern {
BGP(Vec<PropertyPathPattern>),
Join(Box<GraphPattern>, Box<GraphPattern>),
LeftJoin(Box<GraphPattern>, Box<GraphPattern>, Expression),
Filter(Expression, Box<GraphPattern>),
Union(Box<GraphPattern>, Box<GraphPattern>),
Graph(NamedNodeOrVariable, Box<GraphPattern>),
Extend(Box<GraphPattern>, Variable, Expression),
Minus(Box<GraphPattern>, Box<GraphPattern>),
Group(),
Aggregation(),
AggregateJoin(),
OrderBy(Box<GraphPattern>),
Project(Box<GraphPattern>),
Distinct(Box<GraphPattern>),
Reduced(Box<GraphPattern>),
Slice(Box<GraphPattern>, usize, usize),
Join(Box<MultiSetPattern>, Box<MultiSetPattern>),
LeftJoin(Box<MultiSetPattern>, Box<MultiSetPattern>, Expression),
Filter(Expression, Box<MultiSetPattern>),
Union(Box<MultiSetPattern>, Box<MultiSetPattern>),
Graph(NamedNodeOrVariable, Box<MultiSetPattern>),
Extend(Box<MultiSetPattern>, Variable, Expression),
Minus(Box<MultiSetPattern>, Box<MultiSetPattern>),
ToMultiSet(Box<ListPattern>),
}
impl fmt::Display for GraphPattern {
impl fmt::Display for MultiSetPattern {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
GraphPattern::BGP(p) => write!(
MultiSetPattern::BGP(p) => write!(
f,
"BGP({})",
p.iter()
@ -767,36 +759,36 @@ impl fmt::Display for GraphPattern {
.collect::<Vec<String>>()
.join(" . ")
),
GraphPattern::Join(a, b) => write!(f, "Join({}, {})", a, b),
GraphPattern::LeftJoin(a, b, e) => write!(f, "LeftJoin({}, {}, {})", a, b, e),
GraphPattern::Filter(e, p) => write!(f, "Filter({}, {})", e, p),
GraphPattern::Union(a, b) => write!(f, "Union({}, {})", a, b),
GraphPattern::Graph(g, p) => write!(f, "Graph({}, {})", g, p),
GraphPattern::Extend(p, v, e) => write!(f, "Extend({}), {}, {})", p, v, e),
GraphPattern::Minus(a, b) => write!(f, "Minus({}, {})", a, b),
_ => Ok(()), //TODO
MultiSetPattern::Join(a, b) => write!(f, "Join({}, {})", a, b),
MultiSetPattern::LeftJoin(a, b, e) => write!(f, "LeftJoin({}, {}, {})", a, b, e),
MultiSetPattern::Filter(e, p) => write!(f, "Filter({}, {})", e, p),
MultiSetPattern::Union(a, b) => write!(f, "Union({}, {})", a, b),
MultiSetPattern::Graph(g, p) => write!(f, "Graph({}, {})", g, p),
MultiSetPattern::Extend(p, v, e) => write!(f, "Extend({}), {}, {})", p, v, e),
MultiSetPattern::Minus(a, b) => write!(f, "Minus({}, {})", a, b),
MultiSetPattern::ToMultiSet(l) => write!(f, "{}", l),
}
}
}
impl Default for GraphPattern {
impl Default for MultiSetPattern {
fn default() -> Self {
GraphPattern::BGP(Vec::default())
MultiSetPattern::BGP(Vec::default())
}
}
impl From<PropertyPathPattern> for GraphPattern {
impl From<PropertyPathPattern> for MultiSetPattern {
fn from(p: PropertyPathPattern) -> Self {
GraphPattern::BGP(vec![p])
MultiSetPattern::BGP(vec![p])
}
}
struct SparqlGraphPattern<'a>(&'a GraphPattern);
struct SparqlMultiSetPattern<'a>(&'a MultiSetPattern);
impl<'a> fmt::Display for SparqlGraphPattern<'a> {
impl<'a> fmt::Display for SparqlMultiSetPattern<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {
GraphPattern::BGP(p) => {
MultiSetPattern::BGP(p) => {
if p.is_empty() {
write!(f, "{{}}")
} else {
@ -810,43 +802,82 @@ impl<'a> fmt::Display for SparqlGraphPattern<'a> {
)
}
}
GraphPattern::Join(a, b) => {
write!(f, "{} {}", SparqlGraphPattern(&*a), SparqlGraphPattern(&*b))
}
GraphPattern::LeftJoin(a, b, e) => write!(
MultiSetPattern::Join(a, b) => write!(
f,
"{} {}",
SparqlMultiSetPattern(&*a),
SparqlMultiSetPattern(&*b)
),
MultiSetPattern::LeftJoin(a, b, e) => write!(
f,
"{} OPTIONAL {{ {} FILTER({}) }}",
SparqlGraphPattern(&*a),
SparqlGraphPattern(&*b),
SparqlMultiSetPattern(&*a),
SparqlMultiSetPattern(&*b),
SparqlExpression(e)
),
GraphPattern::Filter(e, p) => write!(
MultiSetPattern::Filter(e, p) => write!(
f,
"{} FILTER({})",
SparqlGraphPattern(&*p),
SparqlMultiSetPattern(&*p),
SparqlExpression(e)
),
GraphPattern::Union(a, b) => write!(
MultiSetPattern::Union(a, b) => write!(
f,
"{{ {} }} UNION {{ {} }}",
SparqlGraphPattern(&*a),
SparqlGraphPattern(&*b)
SparqlMultiSetPattern(&*a),
SparqlMultiSetPattern(&*b)
),
GraphPattern::Graph(g, p) => write!(f, "GRAPH {} {{ {} }}", g, SparqlGraphPattern(&*p)),
GraphPattern::Extend(p, v, e) => write!(
MultiSetPattern::Graph(g, p) => {
write!(f, "GRAPH {} {{ {} }}", g, SparqlMultiSetPattern(&*p))
}
MultiSetPattern::Extend(p, v, e) => write!(
f,
"{} BIND({} AS {})",
SparqlGraphPattern(&*p),
SparqlMultiSetPattern(&*p),
SparqlExpression(e),
v
),
GraphPattern::Minus(a, b) => write!(
MultiSetPattern::Minus(a, b) => write!(
f,
"{} MINUS {{ {} }}",
SparqlGraphPattern(&*a),
SparqlGraphPattern(&*b)
SparqlMultiSetPattern(&*a),
SparqlMultiSetPattern(&*b)
),
_ => write!(f, "{{}}"), //TODO
MultiSetPattern::ToMultiSet(l) => write!(f, "{}", SparqlListPattern(&l)),
}
}
}
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)]
pub enum ListPattern {
Data(Vec<Binding>),
ToList(MultiSetPattern),
Group(),
Aggregation(),
AggregateJoin(),
OrderBy(Box<MultiSetPattern>),
Project(Box<MultiSetPattern>),
Distinct(Box<MultiSetPattern>),
Reduced(Box<MultiSetPattern>),
Slice(Box<MultiSetPattern>, usize, usize),
}
impl fmt::Display for ListPattern {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ListPattern::ToList(l) => write!(f, "{}", l),
_ => Ok(()), //TODO
}
}
}
struct SparqlListPattern<'a>(&'a ListPattern);
impl<'a> fmt::Display for SparqlListPattern<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {
ListPattern::ToList(l) => write!(f, "{}", SparqlMultiSetPattern(&l)),
_ => Ok(()), //TODO
}
}
}
@ -957,20 +988,20 @@ pub enum Query {
SelectQuery {
selection: Selection,
dataset: Dataset,
filter: GraphPattern,
filter: MultiSetPattern,
},
ConstructQuery {
construct: Vec<TriplePattern>,
dataset: Dataset,
filter: GraphPattern,
filter: MultiSetPattern,
},
DescribeQuery {
dataset: Dataset,
filter: GraphPattern,
filter: MultiSetPattern,
},
AskQuery {
dataset: Dataset,
filter: GraphPattern,
filter: MultiSetPattern,
},
}
@ -986,7 +1017,7 @@ impl fmt::Display for Query {
"SELECT {} {} WHERE {{ {} }}",
selection,
dataset,
SparqlGraphPattern(&filter)
SparqlMultiSetPattern(&filter)
),
Query::ConstructQuery {
construct,
@ -1001,19 +1032,19 @@ impl fmt::Display for Query {
.collect::<Vec<String>>()
.join(" . "),
dataset,
SparqlGraphPattern(&filter)
SparqlMultiSetPattern(&filter)
),
Query::DescribeQuery { dataset, filter } => write!(
f,
"DESCRIBE {} WHERE {{ {} }}",
dataset,
SparqlGraphPattern(&filter)
SparqlMultiSetPattern(&filter)
),
Query::AskQuery { dataset, filter } => write!(
f,
"ASK {} WHERE {{ {} }}",
dataset,
SparqlGraphPattern(&filter)
SparqlMultiSetPattern(&filter)
),
}
}

@ -92,21 +92,21 @@ mod grammar {
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)]
enum PartialGraphPattern {
Optional(GraphPattern),
Minus(GraphPattern),
Optional(MultiSetPattern),
Minus(MultiSetPattern),
Bind(Expression, Variable),
Filter(Expression),
Other(GraphPattern),
Other(MultiSetPattern),
}
fn new_join(l: GraphPattern, r: GraphPattern) -> GraphPattern {
fn new_join(l: MultiSetPattern, r: MultiSetPattern) -> MultiSetPattern {
//Avoid to output empty BGPs
if let GraphPattern::BGP(pl) = &l {
if let MultiSetPattern::BGP(pl) = &l {
if pl.is_empty() {
return r;
}
}
if let GraphPattern::BGP(pr) = &r {
if let MultiSetPattern::BGP(pr) = &r {
if pr.is_empty() {
return l;
}
@ -114,11 +114,11 @@ mod grammar {
//Merge BGPs
match (l, r) {
(GraphPattern::BGP(mut pl), GraphPattern::BGP(pr)) => {
(MultiSetPattern::BGP(mut pl), MultiSetPattern::BGP(pr)) => {
pl.extend_from_slice(&pr);
GraphPattern::BGP(pl)
MultiSetPattern::BGP(pl)
}
(l, r) => GraphPattern::Join(Box::new(l), Box::new(r)),
(l, r) => MultiSetPattern::Join(Box::new(l), Box::new(r)),
}
}

@ -46,9 +46,9 @@ SelectQuery -> Query = s:SelectClause _ d:DatasetClauses _ f:WhereClause _ Solut
}
//[8]
SubSelect -> GraphPattern = s:SelectClause _ f:WhereClause _ SolutionModifier _ ValuesClause { //TODO: Modifiers
GraphPattern::default()
/*TODO GraphPattern::SubSelectPattern {
SubSelect -> MultiSetPattern = s:SelectClause _ f:WhereClause _ SolutionModifier _ ValuesClause { //TODO: Modifiers
MultiSetPattern::default()
/*TODO MultiSetPattern::SubSelectPattern {
selection: s,
filter: Box::new(f)
}*/
@ -81,7 +81,7 @@ ConstructQuery -> Query =
Query::ConstructQuery {
construct: c.clone(),
dataset: d,
filter: GraphPattern::BGP(c.into_iter().map(|p| PropertyPathPattern::from(p)).collect())
filter: MultiSetPattern::BGP(c.into_iter().map(|p| PropertyPathPattern::from(p)).collect())
}
}
@ -91,7 +91,7 @@ ConstructQuery_optional_triple_template -> Vec<TriplePattern> = TriplesTemplate
DescribeQuery -> Query = "DESCRIBE"i _ ('*' / (VarOrIri _)+) _ d:DatasetClauses f:WhereClause? _ SolutionModifier {
Query::DescribeQuery {
dataset: d,
filter: f.unwrap_or_else(GraphPattern::default)
filter: f.unwrap_or_else(MultiSetPattern::default)
}
}
@ -123,7 +123,7 @@ NamedGraphClause -> Dataset = "NAMED"i _ s:SourceSelector {
SourceSelector -> NamedNode = iri
//[17]
WhereClause -> GraphPattern = "WHERE"i? _ p:GroupGraphPattern { p }
WhereClause -> MultiSetPattern = "WHERE"i? _ p:GroupGraphPattern { p }
//[18]
SolutionModifier -> () = GroupClause? _ HavingClause? _ OrderClause? _ LimitOffsetClauses?
@ -158,7 +158,7 @@ LimitClause -> () = "LIMIT"i _ INTEGER
OffsetClause -> () = "OFFSET"i _ INTEGER
//[28]
ValuesClause -> Option<GraphPattern> =
ValuesClause -> Option<MultiSetPattern> =
"VALUES"i _ p:DataBlock { Some(p) } /
{ None }
@ -169,33 +169,33 @@ TriplesTemplate -> Vec<TriplePattern> = p:TriplesTemplate_item **<1,> ('.' _) '.
TriplesTemplate_item -> Vec<TriplePattern> = p:TriplesSameSubject _ { p }
//[53]
GroupGraphPattern -> GraphPattern =
GroupGraphPattern -> MultiSetPattern =
'{' _ p:GroupGraphPatternSub _ '}' { p } /
'{' _ p:SubSelect _ '}' { p }
//[54]
GroupGraphPatternSub -> GraphPattern = a:TriplesBlock? _ b:GroupGraphPatternSub_item* {
let mut p = a.map(|v| vec![PartialGraphPattern::Other(GraphPattern::BGP(v))]).unwrap_or_else(|| vec![]);
GroupGraphPatternSub -> MultiSetPattern = a:TriplesBlock? _ b:GroupGraphPatternSub_item* {
let mut p = a.map(|v| vec![PartialGraphPattern::Other(MultiSetPattern::BGP(v))]).unwrap_or_else(|| vec![]);
for v in b {
p.extend_from_slice(&v)
}
let mut filter: Option<Expression> = None;
let mut g = GraphPattern::default();
let mut g = MultiSetPattern::default();
for e in p {
match e {
PartialGraphPattern::Optional(p) => match p {
GraphPattern::Filter(f, a2) => {
g = GraphPattern::LeftJoin(Box::new(g), a2, f)
MultiSetPattern::Filter(f, a2) => {
g = MultiSetPattern::LeftJoin(Box::new(g), a2, f)
}
a => {
g = GraphPattern::LeftJoin(Box::new(g), Box::new(a), Literal::from(true).into())
g = MultiSetPattern::LeftJoin(Box::new(g), Box::new(a), Literal::from(true).into())
}
}
PartialGraphPattern::Minus(p) => {
g = GraphPattern::Minus(Box::new(g), Box::new(p))
g = MultiSetPattern::Minus(Box::new(g), Box::new(p))
}
PartialGraphPattern::Bind(expr, var) => {
g = GraphPattern::Extend(Box::new(g), var, expr)
g = MultiSetPattern::Extend(Box::new(g), var, expr)
}
PartialGraphPattern::Filter(expr) => match filter {
Some(f) => { filter = Some(Expression::AndExpression(Box::new(f), Box::new(expr))) },
@ -205,13 +205,13 @@ GroupGraphPatternSub -> GraphPattern = a:TriplesBlock? _ b:GroupGraphPatternSub_
}
}
match filter {
Some(filter) => GraphPattern::Filter(filter, Box::new(g)),
Some(filter) => MultiSetPattern::Filter(filter, Box::new(g)),
None => g
}
}
GroupGraphPatternSub_item -> Vec<PartialGraphPattern> = a:GraphPatternNotTriples _ ('.' _)? b:TriplesBlock? _ {
let mut result = vec![a];
b.map(|v| result.push(PartialGraphPattern::Other(GraphPattern::BGP(v))));
b.map(|v| result.push(PartialGraphPattern::Other(MultiSetPattern::BGP(v))));
result
}
@ -237,13 +237,13 @@ OptionalGraphPattern -> PartialGraphPattern = "OPTIONAL"i _ p:GroupGraphPattern
//[58]
GraphGraphPattern -> PartialGraphPattern = "GRAPH"i _ g:VarOrIri _ p:GroupGraphPattern {
PartialGraphPattern::Other(GraphPattern::Graph(g, Box::new(p)))
PartialGraphPattern::Other(MultiSetPattern::Graph(g, Box::new(p)))
}
//[59]
ServiceGraphPattern -> PartialGraphPattern = "SERVICE"i _ "SILENT"i? _ s:VarOrIri _ p:GroupGraphPattern {
PartialGraphPattern::Other(GraphPattern::default())
//TODO PartialGraphPattern::Other(GraphPattern::ServicePattern(s, Box::new(p)))
PartialGraphPattern::Other(MultiSetPattern::default())
//TODO PartialGraphPattern::Other(MultiSetPattern::ServicePattern(s, Box::new(p)))
}
//[60]
@ -255,27 +255,29 @@ Bind -> PartialGraphPattern = "BIND"i _ '(' _ e:Expression _ "AS"i _ v:Var _ ')'
InlineData -> PartialGraphPattern = "VALUES"i _ p:DataBlock { PartialGraphPattern::Other(p) }
//[62]
DataBlock -> GraphPattern = InlineDataOneVar / InlineDataFull
DataBlock -> MultiSetPattern = l:(InlineDataOneVar / InlineDataFull) {
MultiSetPattern::ToMultiSet(Box::new(ListPattern::Data(l)))
}
//[63]
InlineDataOneVar -> GraphPattern = var:Var _ '{' _ d:InlineDataOneVar_value* '}' {
GraphPattern::Multiset(d.into_iter().map(|val| {
InlineDataOneVar -> Vec<Binding> = var:Var _ '{' _ d:InlineDataOneVar_value* '}' {
d.into_iter().map(|val| {
let mut bindings = Binding::default();
val.map(|v| bindings.insert(var.clone(), v));
bindings
}).collect())
}).collect()
}
InlineDataOneVar_value -> Option<Term> = t:DataBlockValue { t }
//[64]
InlineDataFull -> GraphPattern = '(' _ vars:InlineDataFull_var* _ ')' _ '{' _ val:InlineDataFull_values* '}' {
GraphPattern::Multiset(val.into_iter().map(|vals| {
InlineDataFull -> Vec<Binding> = '(' _ vars:InlineDataFull_var* _ ')' _ '{' _ val:InlineDataFull_values* '}' {
val.into_iter().map(|vals| {
let mut bindings = Binding::default();
for (var, val) in vars.iter().zip(vals.into_iter()) {
val.map(|v| bindings.insert(var.clone(), v));
}
bindings
}).collect())
}).collect()
}
InlineDataFull_var -> Variable = v:Var _ { v }
InlineDataFull_values -> Vec<Option<Term>> = '(' _ v:InlineDataFull_value* _ ')' _ { v }
@ -297,10 +299,10 @@ MinusGraphPattern -> PartialGraphPattern = "MINUS"i _ p: GroupGraphPattern {
//[67]
GroupOrUnionGraphPattern -> PartialGraphPattern = p:GroupOrUnionGraphPattern_item **<1,> ("UNION"i _) {?
not_empty_fold(p.into_iter(), |a, b| {
GraphPattern::Union(Box::new(a), Box::new(b))
MultiSetPattern::Union(Box::new(a), Box::new(b))
}).map(PartialGraphPattern::Other)
}
GroupOrUnionGraphPattern_item -> GraphPattern = p:GroupGraphPattern _ { p }
GroupOrUnionGraphPattern_item -> MultiSetPattern = p:GroupGraphPattern _ { p }
//[68]
Filter -> PartialGraphPattern = "FILTER"i _ c:Constraint {

Loading…
Cancel
Save