Merges MultiSetPattern and ListPattern

It would be nice for optimizations to intricate the two together
pull/10/head
Tpt 6 years ago
parent fb152aa3ee
commit 9659e33251
  1. 539
      lib/src/sparql/algebra.rs
  2. 81
      lib/src/sparql/eval.rs
  3. 48
      lib/src/sparql/parser.rs
  4. 48
      lib/src/sparql/sparql_grammar.rustpeg

@ -474,7 +474,7 @@ pub enum Expression {
IsNumericFunctionCall(Box<Expression>),
RegexFunctionCall(Box<Expression>, Box<Expression>, Option<Box<Expression>>),
CustomFunctionCall(NamedNode, Vec<Expression>),
ExistsFunctionCall(Box<MultiSetPattern>),
ExistsFunctionCall(Box<GraphPattern>),
}
impl fmt::Display for Expression {
@ -700,7 +700,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 {{ {} }}", SparqlMultiSetPattern(&*p))
write!(f, "NOT EXISTS {{ {} }}", SparqlGraphPattern(&*p))
}
e => write!(f, "!{}", e),
},
@ -890,31 +890,36 @@ impl<'a> fmt::Display for SparqlExpression<'a> {
.join(", ")
),
Expression::ExistsFunctionCall(p) => {
write!(f, "EXISTS {{ {} }}", SparqlMultiSetPattern(&*p))
write!(f, "EXISTS {{ {} }}", SparqlGraphPattern(&*p))
}
}
}
}
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)]
pub enum MultiSetPattern {
pub enum GraphPattern {
BGP(Vec<TripleOrPathPattern>),
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>),
Service(NamedNodeOrVariable, Box<MultiSetPattern>, bool),
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>),
Service(NamedNodeOrVariable, Box<GraphPattern>, bool),
AggregateJoin(GroupPattern, BTreeMap<Aggregation, Variable>),
Data(StaticBindings),
OrderBy(Box<GraphPattern>, Vec<OrderComparator>),
Project(Box<GraphPattern>, Vec<Variable>),
Distinct(Box<GraphPattern>),
Reduced(Box<GraphPattern>),
Slice(Box<GraphPattern>, usize, Option<usize>),
}
impl fmt::Display for MultiSetPattern {
impl fmt::Display for GraphPattern {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
MultiSetPattern::BGP(p) => write!(
GraphPattern::BGP(p) => write!(
f,
"BGP({})",
p.iter()
@ -922,16 +927,15 @@ impl fmt::Display for MultiSetPattern {
.collect::<Vec<String>>()
.join(" . ")
),
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),
MultiSetPattern::Service(n, p, s) => write!(f, "Service({}, {}, {})", n, p, s),
MultiSetPattern::AggregateJoin(g, a) => write!(
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),
GraphPattern::Service(n, p, s) => write!(f, "Service({}, {}, {})", n, p, s),
GraphPattern::AggregateJoin(g, a) => write!(
f,
"AggregateJoin({}, {})",
g,
@ -940,29 +944,66 @@ impl fmt::Display for MultiSetPattern {
.collect::<Vec<String>>()
.join(", ")
),
GraphPattern::Data(bs) => {
let variables = bs.variables();
write!(f, "{{ ")?;
for values in bs.values_iter() {
write!(f, "{{")?;
for i in 0..values.len() {
if let Some(ref val) = values[i] {
write!(f, " {} → {} ", variables[i], val)?;
}
}
write!(f, "}}")?;
}
write!(f, "}}")
}
GraphPattern::OrderBy(l, o) => write!(
f,
"OrderBy({}, ({}))",
l,
o.iter()
.map(|c| c.to_string())
.collect::<Vec<String>>()
.join(", ")
),
GraphPattern::Project(l, pv) => write!(
f,
"Project({}, ({}))",
l,
pv.iter()
.map(|v| v.to_string())
.collect::<Vec<String>>()
.join(", ")
),
GraphPattern::Distinct(l) => write!(f, "Distinct({})", l),
GraphPattern::Reduced(l) => write!(f, "Reduce({})", l),
GraphPattern::Slice(l, start, length) => write!(
f,
"Slice({}, {}, {})",
l,
start,
length
.map(|l| l.to_string())
.unwrap_or_else(|| '?'.to_string())
),
}
impl Default for MultiSetPattern {
fn default() -> Self {
MultiSetPattern::BGP(Vec::default())
}
}
impl From<TripleOrPathPattern> for MultiSetPattern {
fn from(p: TripleOrPathPattern) -> Self {
MultiSetPattern::BGP(vec![p])
impl Default for GraphPattern {
fn default() -> Self {
GraphPattern::BGP(Vec::default())
}
}
impl From<ListPattern> for MultiSetPattern {
fn from(pattern: ListPattern) -> Self {
MultiSetPattern::ToMultiSet(Box::new(pattern))
impl From<TripleOrPathPattern> for GraphPattern {
fn from(p: TripleOrPathPattern) -> Self {
GraphPattern::BGP(vec![p])
}
}
impl MultiSetPattern {
impl GraphPattern {
pub fn visible_variables(&self) -> BTreeSet<&Variable> {
let mut vars = BTreeSet::default();
self.add_visible_variables(&mut vars);
@ -971,7 +1012,7 @@ impl MultiSetPattern {
fn add_visible_variables<'a>(&'a self, vars: &mut BTreeSet<&'a Variable>) {
match self {
MultiSetPattern::BGP(p) => {
GraphPattern::BGP(p) => {
for pattern in p {
match pattern {
TripleOrPathPattern::Triple(tp) => {
@ -996,28 +1037,33 @@ impl MultiSetPattern {
}
}
}
MultiSetPattern::Join(a, b) => {
GraphPattern::Join(a, b) => {
a.add_visible_variables(vars);
b.add_visible_variables(vars);
}
MultiSetPattern::LeftJoin(a, b, _) => {
GraphPattern::LeftJoin(a, b, _) => {
a.add_visible_variables(vars);
b.add_visible_variables(vars);
}
MultiSetPattern::Filter(_, p) => p.add_visible_variables(vars),
MultiSetPattern::Union(a, b) => {
GraphPattern::Filter(_, p) => p.add_visible_variables(vars),
GraphPattern::Union(a, b) => {
a.add_visible_variables(vars);
b.add_visible_variables(vars);
}
MultiSetPattern::Graph(_, p) => p.add_visible_variables(vars),
MultiSetPattern::Extend(p, v, _) => {
GraphPattern::Graph(_, p) => p.add_visible_variables(vars),
GraphPattern::Extend(p, v, _) => {
p.add_visible_variables(vars);
adds_if_has_name(vars, &v);
}
MultiSetPattern::Minus(a, _) => a.add_visible_variables(vars),
MultiSetPattern::ToMultiSet(l) => l.add_visible_variables(vars),
MultiSetPattern::Service(_, p, _) => p.add_visible_variables(vars),
MultiSetPattern::AggregateJoin(_, a) => vars.extend(a.iter().map(|(_, v)| v)),
GraphPattern::Minus(a, _) => a.add_visible_variables(vars),
GraphPattern::Service(_, p, _) => p.add_visible_variables(vars),
GraphPattern::AggregateJoin(_, a) => vars.extend(a.iter().map(|(_, v)| v)),
GraphPattern::Data(b) => vars.extend(b.variables_iter()),
GraphPattern::OrderBy(l, _) => l.add_visible_variables(vars),
GraphPattern::Project(_, pv) => vars.extend(pv.iter()),
GraphPattern::Distinct(l) => l.add_visible_variables(vars),
GraphPattern::Reduced(l) => l.add_visible_variables(vars),
GraphPattern::Slice(l, _, _) => l.add_visible_variables(vars),
}
}
}
@ -1028,329 +1074,198 @@ fn adds_if_has_name<'a>(vars: &mut BTreeSet<&'a Variable>, var: &'a Variable) {
}
}
struct SparqlMultiSetPattern<'a>(&'a MultiSetPattern);
struct SparqlGraphPattern<'a>(&'a GraphPattern);
impl<'a> fmt::Display for SparqlMultiSetPattern<'a> {
impl<'a> fmt::Display for SparqlGraphPattern<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {
MultiSetPattern::BGP(p) => {
if p.is_empty() {
GraphPattern::BGP(p) => {
for pattern in p {
write!(f, "{} .", SparqlTripleOrPathPattern(pattern))?
}
Ok(())
} else {
write!(
f,
"{}",
p.iter()
.map(|v| SparqlTripleOrPathPattern(v).to_string())
.collect::<Vec<String>>()
.join(" . ")
)
}
GraphPattern::Join(a, b) => {
write!(f, "{} {}", SparqlGraphPattern(&*a), SparqlGraphPattern(&*b))
}
MultiSetPattern::Join(a, b) => write!(
f,
"{} {}",
SparqlMultiSetPattern(&*a),
SparqlMultiSetPattern(&*b)
),
MultiSetPattern::LeftJoin(a, b, e) => write!(
GraphPattern::LeftJoin(a, b, e) => write!(
f,
"{} OPTIONAL {{ {} FILTER({}) }}",
SparqlMultiSetPattern(&*a),
SparqlMultiSetPattern(&*b),
SparqlGraphPattern(&*a),
SparqlGraphPattern(&*b),
SparqlExpression(e)
),
MultiSetPattern::Filter(e, p) => write!(
GraphPattern::Filter(e, p) => write!(
f,
"{} FILTER({})",
SparqlMultiSetPattern(&*p),
SparqlGraphPattern(&*p),
SparqlExpression(e)
),
MultiSetPattern::Union(a, b) => write!(
GraphPattern::Union(a, b) => write!(
f,
"{{ {} }} UNION {{ {} }}",
SparqlMultiSetPattern(&*a),
SparqlMultiSetPattern(&*b)
SparqlGraphPattern(&*a),
SparqlGraphPattern(&*b),
),
MultiSetPattern::Graph(g, p) => {
write!(f, "GRAPH {} {{ {} }}", g, SparqlMultiSetPattern(&*p))
GraphPattern::Graph(g, p) => {
write!(f, "GRAPH {} {{ {} }}", g, SparqlGraphPattern(&*p),)
}
MultiSetPattern::Extend(p, v, e) => write!(
GraphPattern::Extend(p, v, e) => write!(
f,
"{} BIND({} AS {})",
SparqlMultiSetPattern(&*p),
SparqlGraphPattern(&*p),
SparqlExpression(e),
v
),
MultiSetPattern::Minus(a, b) => write!(
GraphPattern::Minus(a, b) => write!(
f,
"{} MINUS {{ {} }}",
SparqlMultiSetPattern(&*a),
SparqlMultiSetPattern(&*b)
SparqlGraphPattern(&*a),
SparqlGraphPattern(&*b)
),
MultiSetPattern::ToMultiSet(l) => write!(
f,
"{{ {} }}",
SparqlListPattern {
algebra: &l,
dataset: &EMPTY_DATASET
}
),
MultiSetPattern::Service(n, p, s) => if *s {
write!(
f,
"SERVICE SILENT {} {{ {} }}",
n,
SparqlMultiSetPattern(&*p)
)
GraphPattern::Service(n, p, s) => if *s {
write!(f, "SERVICE SILENT {} {{ {} }}", n, SparqlGraphPattern(&*p))
} else {
write!(f, "SERVICE {} {{ {} }}", n, SparqlGraphPattern(&*p))
},
GraphPattern::Data(bs) => if bs.is_empty() {
Ok(())
} else {
write!(f, "SERVICE {} {{ {} }}", n, SparqlMultiSetPattern(&*p))
write!(f, "VALUES ( ")?;
for var in bs.variables() {
write!(f, "{} ", var)?;
}
write!(f, ") {{ ")?;
for values in bs.values_iter() {
write!(f, "( ")?;
for val in values {
match val {
Some(val) => write!(f, "{} ", val),
None => write!(f, "UNDEF "),
}?;
}
write!(f, ") ")?;
}
write!(f, " }}")
},
MultiSetPattern::AggregateJoin(GroupPattern(group, p), agg) => write!(
GraphPattern::AggregateJoin(GroupPattern(group, p), agg) => write!(
f,
"{{ SELECT {} WHERE {{ {} }} GROUP BY {} }}",
agg.iter()
.map(|(a, v)| format!("({} AS {})", SparqlAggregation(&a), v))
.collect::<Vec<String>>()
.join(" "),
SparqlMultiSetPattern(p),
SparqlGraphPattern(&*p),
group
.iter()
.map(|e| format!("({})", e.to_string()))
.collect::<Vec<String>>()
.join(" ")
),
p => write!(
f,
"{{ {} }}",
SparqlGraphRootPattern {
algebra: p,
dataset: &EMPTY_DATASET
}
),
}
}
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)]
pub struct GroupPattern(pub Vec<Expression>, pub Box<MultiSetPattern>);
impl fmt::Display for GroupPattern {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"Group(({}), {})",
self.0
.iter()
.map(|c| c.to_string())
.collect::<Vec<String>>()
.join(", "),
self.1
)
}
}
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)]
pub enum ListPattern {
Data(StaticBindings),
ToList(MultiSetPattern),
OrderBy(Box<ListPattern>, Vec<OrderComparator>),
Project(Box<ListPattern>, Vec<Variable>),
Distinct(Box<ListPattern>),
Reduced(Box<ListPattern>),
Slice(Box<ListPattern>, usize, Option<usize>),
struct SparqlGraphRootPattern<'a> {
algebra: &'a GraphPattern,
dataset: &'a DatasetSpec,
}
impl fmt::Display for ListPattern {
impl<'a> fmt::Display for SparqlGraphRootPattern<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ListPattern::Data(bs) => {
let variables = bs.variables();
write!(f, "{{ ")?;
for values in bs.values_iter() {
write!(f, "{{")?;
for i in 0..values.len() {
if let Some(ref val) = values[i] {
write!(f, " {} → {} ", variables[i], val)?;
}
}
write!(f, "}}")?;
}
write!(f, "}}")
let mut distinct = false;
let mut reduced = false;
let mut order = None;
let mut start = 0;
let mut length = None;
let mut project: &[Variable] = &[];
let mut child = self.algebra;
loop {
match child {
GraphPattern::OrderBy(l, o) => {
order = Some(o);
child = &*l;
}
GraphPattern::Project(l, pv) if project.is_empty() => {
project = pv;
child = &*l;
}
GraphPattern::Distinct(l) => {
distinct = true;
child = &*l;
}
GraphPattern::Reduced(l) => {
reduced = true;
child = &*l;
}
GraphPattern::Slice(l, s, len) => {
start = *s;
length = *len;
child = l;
}
p => {
write!(f, "SELECT ")?;
if distinct {
write!(f, "DISTINCT ")?;
}
if reduced {
write!(f, "REDUCED ")?;
}
ListPattern::ToList(l) => write!(f, "{}", l),
ListPattern::OrderBy(l, o) => write!(
write!(
f,
"OrderBy({}, ({}))",
l,
o.iter()
.map(|c| c.to_string())
.collect::<Vec<String>>()
.join(", ")
),
ListPattern::Project(l, pv) => write!(
"{} {} WHERE {{ {} }}",
build_sparql_select_arguments(project),
self.dataset,
SparqlGraphPattern(p)
)?;
if let Some(order) = order {
write!(
f,
"Project({}, ({}))",
l,
pv.iter()
.map(|v| v.to_string())
" ORDER BY {}",
order
.iter()
.map(|c| SparqlOrderComparator(c).to_string())
.collect::<Vec<String>>()
.join(", ")
),
ListPattern::Distinct(l) => write!(f, "Distinct({})", l),
ListPattern::Reduced(l) => write!(f, "Reduce({})", l),
ListPattern::Slice(l, start, length) => write!(
f,
"Slice({}, {}, {})",
l,
start,
length
.map(|l| l.to_string())
.unwrap_or_else(|| '?'.to_string())
),
}
}
}
impl Default for ListPattern {
fn default() -> Self {
ListPattern::Data(StaticBindings::default())
.join(" ")
)?;
}
if start > 0 {
write!(f, " OFFSET {}", start)?;
}
impl From<MultiSetPattern> for ListPattern {
fn from(pattern: MultiSetPattern) -> Self {
ListPattern::ToList(pattern)
if let Some(length) = length {
write!(f, " LIMIT {}", length)?;
}
return Ok(());
}
impl ListPattern {
pub fn visible_variables<'a>(&'a self) -> BTreeSet<&'a Variable> {
let mut vars = BTreeSet::default();
self.add_visible_variables(&mut vars);
vars
}
fn add_visible_variables<'a>(&'a self, vars: &mut BTreeSet<&'a Variable>) {
match self {
ListPattern::Data(b) => vars.extend(b.variables_iter()),
ListPattern::ToList(p) => p.add_visible_variables(vars),
ListPattern::OrderBy(l, _) => l.add_visible_variables(vars),
ListPattern::Project(_, pv) => vars.extend(pv.iter()),
ListPattern::Distinct(l) => l.add_visible_variables(vars),
ListPattern::Reduced(l) => l.add_visible_variables(vars),
ListPattern::Slice(l, _, _) => l.add_visible_variables(vars),
}
}
}
struct SparqlListPattern<'a> {
algebra: &'a ListPattern,
dataset: &'a DatasetSpec,
}
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)]
pub struct GroupPattern(pub Vec<Expression>, pub Box<GraphPattern>);
impl<'a> fmt::Display for SparqlListPattern<'a> {
impl fmt::Display for GroupPattern {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.algebra {
ListPattern::Data(bs) => if bs.is_empty() {
Ok(())
} else {
write!(f, "VALUES ( ")?;
for var in bs.variables() {
write!(f, "{} ", var)?;
}
write!(f, ") {{ ")?;
for values in bs.values_iter() {
write!(f, "( ")?;
for val in values {
match val {
Some(val) => write!(f, "{} ", val),
None => write!(f, "UNDEF "),
}?;
}
write!(f, ") ")?;
}
write!(f, " }}")
},
ListPattern::ToList(l) => write!(f, "{{ {} }}", SparqlMultiSetPattern(&*l)),
ListPattern::OrderBy(l, o) => write!(
f,
"{} ORDER BY {}",
SparqlListPattern {
algebra: &*l,
dataset: self.dataset
},
o.iter()
.map(|c| SparqlOrderComparator(c).to_string())
.collect::<Vec<String>>()
.join(" ")
),
ListPattern::Project(l, pv) => write!(
f,
"SELECT {} {} WHERE {}",
build_sparql_select_arguments(pv),
self.dataset,
SparqlListPattern {
algebra: &*l,
dataset: &EMPTY_DATASET
}
),
ListPattern::Distinct(l) => match l.as_ref() {
ListPattern::Project(l, pv) => write!(
f,
"SELECT DISTINCT {} {} WHERE {}",
build_sparql_select_arguments(pv),
self.dataset,
SparqlListPattern {
algebra: &*l,
dataset: &EMPTY_DATASET
}
),
l => write!(
f,
"DISTINCT {}",
SparqlListPattern {
algebra: &l,
dataset: self.dataset
}
),
},
ListPattern::Reduced(l) => match l.as_ref() {
ListPattern::Project(l, pv) => write!(
f,
"SELECT REDUCED {} {} WHERE {}",
build_sparql_select_arguments(pv),
self.dataset,
SparqlListPattern {
algebra: &*l,
dataset: &EMPTY_DATASET
}
),
l => write!(
f,
"REDUCED {}",
SparqlListPattern {
algebra: &l,
dataset: self.dataset
}
),
},
ListPattern::Slice(l, start, length) => length
.map(|length| {
write!(
f,
"{} LIMIT {} OFFSET {}",
SparqlListPattern {
algebra: &*l,
dataset: self.dataset
},
start,
length
)
}).unwrap_or_else(|| {
write!(
f,
"{} LIMIT {}",
SparqlListPattern {
algebra: &*l,
dataset: self.dataset
},
start
"Group(({}), {})",
self.0
.iter()
.map(|c| c.to_string())
.collect::<Vec<String>>()
.join(", "),
self.1
)
}),
}
}
}
@ -1589,20 +1504,20 @@ lazy_static! {
pub enum Query {
SelectQuery {
dataset: DatasetSpec,
algebra: ListPattern,
algebra: GraphPattern,
},
ConstructQuery {
construct: Vec<TriplePattern>,
dataset: DatasetSpec,
algebra: ListPattern,
algebra: GraphPattern,
},
DescribeQuery {
dataset: DatasetSpec,
algebra: ListPattern,
algebra: GraphPattern,
},
AskQuery {
dataset: DatasetSpec,
algebra: ListPattern,
algebra: GraphPattern,
},
}
@ -1612,7 +1527,7 @@ impl fmt::Display for Query {
Query::SelectQuery { dataset, algebra } => write!(
f,
"{}",
SparqlListPattern {
SparqlGraphRootPattern {
algebra: &algebra,
dataset: &dataset
}
@ -1630,7 +1545,7 @@ impl fmt::Display for Query {
.collect::<Vec<String>>()
.join(" . "),
dataset,
SparqlListPattern {
SparqlGraphRootPattern {
algebra: &algebra,
dataset: &EMPTY_DATASET
}
@ -1639,7 +1554,7 @@ impl fmt::Display for Query {
f,
"DESCRIBE * {} WHERE {{ {} }}",
dataset,
SparqlListPattern {
SparqlGraphRootPattern {
algebra: &algebra,
dataset: &EMPTY_DATASET
}
@ -1648,7 +1563,7 @@ impl fmt::Display for Query {
f,
"ASK {} WHERE {{ {} }}",
dataset,
SparqlListPattern {
SparqlGraphRootPattern {
algebra: &algebra,
dataset: &EMPTY_DATASET
}

@ -163,47 +163,20 @@ impl<S: EncodedQuadsStore> SparqlEvaluator<S> {
match query {
Query::SelectQuery { algebra, dataset } => {
Ok(QueryResult::Bindings(self.decode_bindings(
self.eval_list_pattern(algebra, EncodedBindingsIterator::default())?,
self.eval_graph_pattern(algebra, EncodedBindingsIterator::default())?,
)))
}
_ => unimplemented!(),
}
}
fn eval_list_pattern(
fn eval_graph_pattern(
&self,
pattern: &ListPattern,
pattern: &GraphPattern,
from: EncodedBindingsIterator,
) -> Result<EncodedBindingsIterator> {
match pattern {
ListPattern::Data(bs) => Ok(self.encode_bindings(bs)),
ListPattern::ToList(l) => self.eval_multi_set_pattern(l, from),
ListPattern::OrderBy(l, o) => self.eval_list_pattern(l, from), //TODO
ListPattern::Project(l, new_variables) => Ok(self
.eval_list_pattern(l, from)?
.project(new_variables.to_vec())),
ListPattern::Distinct(l) => Ok(self.eval_list_pattern(l, from)?.unique()),
ListPattern::Reduced(l) => self.eval_list_pattern(l, from),
ListPattern::Slice(l, start, length) => {
let mut iter = self.eval_list_pattern(l, from)?;
if *start > 0 {
iter = iter.skip(*start);
}
if let Some(length) = length {
iter = iter.take(*length);
}
Ok(iter)
}
}
}
fn eval_multi_set_pattern(
&self,
pattern: &MultiSetPattern,
from: EncodedBindingsIterator,
) -> Result<EncodedBindingsIterator> {
match pattern {
MultiSetPattern::BGP(p) => {
GraphPattern::BGP(p) => {
let mut iter = from;
for pattern in p {
iter = match pattern {
@ -215,13 +188,13 @@ impl<S: EncodedQuadsStore> SparqlEvaluator<S> {
}
Ok(iter)
}
MultiSetPattern::Join(a, b) => {
self.eval_multi_set_pattern(b, self.eval_multi_set_pattern(a, from)?)
GraphPattern::Join(a, b) => {
self.eval_graph_pattern(b, self.eval_graph_pattern(a, from)?)
}
MultiSetPattern::LeftJoin(a, b, e) => unimplemented!(),
MultiSetPattern::Filter(e, p) => {
GraphPattern::LeftJoin(a, b, e) => unimplemented!(),
GraphPattern::Filter(e, p) => {
let EncodedBindingsIterator { variables, iter } =
self.eval_multi_set_pattern(p, from)?;
self.eval_graph_pattern(p, from)?;
let expression = e.clone();
let evaluator = Self {
store: self.store.clone(),
@ -239,18 +212,34 @@ impl<S: EncodedQuadsStore> SparqlEvaluator<S> {
})),
})
}
MultiSetPattern::Union(a, b) => {
GraphPattern::Union(a, b) => {
let (from1, from2) = from.duplicate();
Ok(self
.eval_multi_set_pattern(a, from1)?
.chain(self.eval_multi_set_pattern(b, from2)?))
}
MultiSetPattern::Graph(g, p) => unimplemented!(),
MultiSetPattern::Extend(p, v, e) => unimplemented!(),
MultiSetPattern::Minus(a, b) => unimplemented!(),
MultiSetPattern::ToMultiSet(l) => self.eval_list_pattern(l, from),
MultiSetPattern::Service(n, p, s) => unimplemented!(),
MultiSetPattern::AggregateJoin(g, a) => unimplemented!(),
.eval_graph_pattern(a, from1)?
.chain(self.eval_graph_pattern(b, from2)?))
}
GraphPattern::Graph(g, p) => unimplemented!(),
GraphPattern::Extend(p, v, e) => unimplemented!(),
GraphPattern::Minus(a, b) => unimplemented!(),
GraphPattern::Service(n, p, s) => unimplemented!(),
GraphPattern::AggregateJoin(g, a) => unimplemented!(),
GraphPattern::Data(bs) => Ok(self.encode_bindings(bs)),
GraphPattern::OrderBy(l, o) => self.eval_graph_pattern(l, from), //TODO
GraphPattern::Project(l, new_variables) => Ok(self
.eval_graph_pattern(l, from)?
.project(new_variables.to_vec())),
GraphPattern::Distinct(l) => Ok(self.eval_graph_pattern(l, from)?.unique()),
GraphPattern::Reduced(l) => self.eval_graph_pattern(l, from),
GraphPattern::Slice(l, start, length) => {
let mut iter = self.eval_graph_pattern(l, from)?;
if *start > 0 {
iter = iter.skip(*start);
}
if let Some(length) = length {
iter = iter.take(*length);
}
Ok(iter)
}
}
}

@ -140,21 +140,21 @@ mod grammar {
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)]
enum PartialGraphPattern {
Optional(MultiSetPattern),
Minus(MultiSetPattern),
Optional(GraphPattern),
Minus(GraphPattern),
Bind(Expression, Variable),
Filter(Expression),
Other(MultiSetPattern),
Other(GraphPattern),
}
fn new_join(l: MultiSetPattern, r: MultiSetPattern) -> MultiSetPattern {
fn new_join(l: GraphPattern, r: GraphPattern) -> GraphPattern {
//Avoid to output empty BGPs
if let MultiSetPattern::BGP(pl) = &l {
if let GraphPattern::BGP(pl) = &l {
if pl.is_empty() {
return r;
}
}
if let MultiSetPattern::BGP(pr) = &r {
if let GraphPattern::BGP(pr) = &r {
if pr.is_empty() {
return l;
}
@ -162,11 +162,11 @@ mod grammar {
//Merge BGPs
match (l, r) {
(MultiSetPattern::BGP(mut pl), MultiSetPattern::BGP(pr)) => {
(GraphPattern::BGP(mut pl), GraphPattern::BGP(pr)) => {
pl.extend_from_slice(&pr);
MultiSetPattern::BGP(pl)
GraphPattern::BGP(pl)
}
(l, r) => MultiSetPattern::Join(Box::new(l), Box::new(r)),
(l, r) => GraphPattern::Join(Box::new(l), Box::new(r)),
}
}
@ -207,28 +207,28 @@ mod grammar {
fn build_select(
select: Selection,
wher: MultiSetPattern,
wher: GraphPattern,
group: Option<(Vec<Expression>, Vec<(Expression, Variable)>)>,
having: Option<Expression>,
order_by: Option<Vec<OrderComparator>>,
offset_limit: Option<(usize, Option<usize>)>,
values: Option<MultiSetPattern>,
values: Option<GraphPattern>,
state: &mut ParserState,
) -> ListPattern {
) -> GraphPattern {
let mut p = wher;
//GROUP BY
if let Some((clauses, binds)) = group {
for (e, v) in binds {
p = MultiSetPattern::Extend(Box::new(p), v, e);
p = GraphPattern::Extend(Box::new(p), v, e);
}
let g = GroupPattern(clauses, Box::new(p));
p = MultiSetPattern::AggregateJoin(g, state.aggregations.clone());
p = GraphPattern::AggregateJoin(g, state.aggregations.clone());
state.aggregations = BTreeMap::default();
}
if !state.aggregations.is_empty() {
let g = GroupPattern(vec![Literal::from(1).into()], Box::new(p));
p = MultiSetPattern::AggregateJoin(g, state.aggregations.clone());
p = GraphPattern::AggregateJoin(g, state.aggregations.clone());
state.aggregations = BTreeMap::default();
}
@ -236,12 +236,12 @@ mod grammar {
//HAVING
if let Some(ex) = having {
p = MultiSetPattern::Filter(ex, Box::new(p));
p = GraphPattern::Filter(ex, Box::new(p));
}
//VALUES
if let Some(data) = values {
p = MultiSetPattern::Join(Box::new(p), Box::new(data));
p = new_join(p, data);
}
//SELECT
@ -254,7 +254,7 @@ mod grammar {
SelectionMember::Expression(e, v) => if pv.contains(&v) {
//TODO: fail
} else {
p = MultiSetPattern::Extend(Box::new(p), v.clone(), e);
p = GraphPattern::Extend(Box::new(p), v.clone(), e);
pv.push(v);
},
}
@ -264,24 +264,24 @@ mod grammar {
pv.extend(p.visible_variables().into_iter().cloned()) //TODO: is it really useful to do a projection?
}
}
let mut m = ListPattern::from(p);
let mut m = GraphPattern::from(p);
//ORDER BY
if let Some(order) = order_by {
m = ListPattern::OrderBy(Box::new(m), order);
m = GraphPattern::OrderBy(Box::new(m), order);
}
//PROJECT
m = ListPattern::Project(Box::new(m), pv);
m = GraphPattern::Project(Box::new(m), pv);
match select.option {
SelectionOption::Distinct => m = ListPattern::Distinct(Box::new(m)),
SelectionOption::Reduced => m = ListPattern::Reduced(Box::new(m)),
SelectionOption::Distinct => m = GraphPattern::Distinct(Box::new(m)),
SelectionOption::Reduced => m = GraphPattern::Reduced(Box::new(m)),
SelectionOption::Default => (),
}
//OFFSET LIMIT
if let Some((offset, limit)) = offset_limit {
m = ListPattern::Slice(Box::new(m), offset, limit)
m = GraphPattern::Slice(Box::new(m), offset, limit)
}
m
}

@ -45,7 +45,7 @@ SelectQuery -> Query = s:SelectClause _ d:DatasetClauses _ w:WhereClause _ g:Gro
}
//[8]
SubSelect -> MultiSetPattern = s:SelectClause _ w:WhereClause _ g:GroupClause? _ h:HavingClause? _ o:OrderClause? _ l:LimitOffsetClauses? _ v:ValuesClause { //TODO: Modifiers
SubSelect -> GraphPattern = s:SelectClause _ w:WhereClause _ g:GroupClause? _ h:HavingClause? _ o:OrderClause? _ l:LimitOffsetClauses? _ v:ValuesClause { //TODO: Modifiers
build_select(s, w, g, h, o, l, v, state).into()
}
@ -82,7 +82,7 @@ ConstructQuery -> Query =
dataset: d,
algebra: build_select(
Selection::default(),
MultiSetPattern::BGP(c.into_iter().map(TripleOrPathPattern::from).collect()),
GraphPattern::BGP(c.into_iter().map(TripleOrPathPattern::from).collect()),
g, h, o, l, v, state
)
}
@ -95,7 +95,7 @@ DescribeQuery -> Query =
"DESCRIBE"i _ '*' _ d:DatasetClauses w:WhereClause? _ g:GroupClause? _ h:HavingClause? _ o:OrderClause? _ l:LimitOffsetClauses? _ v:ValuesClause {
Query::DescribeQuery {
dataset: d,
algebra: build_select(Selection::default(), w.unwrap_or_else(MultiSetPattern::default), g, h, o, l, v, state)
algebra: build_select(Selection::default(), w.unwrap_or_else(GraphPattern::default), g, h, o, l, v, state)
}
} /
"DESCRIBE"i _ p:DescribeQuery_item+ _ d:DatasetClauses w:WhereClause? _ g:GroupClause? _ h:HavingClause? _ o:OrderClause? _ l:LimitOffsetClauses? _ v:ValuesClause {
@ -107,7 +107,7 @@ DescribeQuery -> Query =
NamedNodeOrVariable::NamedNode(n) => SelectionMember::Expression(n.into(), Variable::default()),
NamedNodeOrVariable::Variable(v) => SelectionMember::Variable(v)
}).collect())
}, w.unwrap_or_else(MultiSetPattern::default), g, h, o, l, v, state)
}, w.unwrap_or_else(GraphPattern::default), g, h, o, l, v, state)
}
}
DescribeQuery_item -> NamedNodeOrVariable = i:VarOrIri _ { i }
@ -140,7 +140,7 @@ NamedGraphClause -> DatasetSpec = "NAMED"i _ s:SourceSelector {
SourceSelector -> NamedNode = iri
//[17]
WhereClause -> MultiSetPattern = "WHERE"i? _ p:GroupGraphPattern {
WhereClause -> GraphPattern = "WHERE"i? _ p:GroupGraphPattern {
p
}
@ -203,7 +203,7 @@ OffsetClause -> usize = "OFFSET"i _ o:$(INTEGER) {?
}
//[28]
ValuesClause -> Option<MultiSetPattern> =
ValuesClause -> Option<GraphPattern> =
"VALUES"i _ p:DataBlock { Some(p) } /
{ None }
@ -220,33 +220,33 @@ TriplesTemplate_tail -> Vec<TriplePattern> = '.' _ t:TriplesTemplate? _ {
}
//[53]
GroupGraphPattern -> MultiSetPattern =
GroupGraphPattern -> GraphPattern =
'{' _ p:GroupGraphPatternSub _ '}' { p } /
'{' _ p:SubSelect _ '}' { p }
//[54]
GroupGraphPatternSub -> MultiSetPattern = a:TriplesBlock? _ b:GroupGraphPatternSub_item* {
let mut p = a.map(|v| vec![PartialGraphPattern::Other(MultiSetPattern::BGP(v))]).unwrap_or_else(|| vec![]);
GroupGraphPatternSub -> GraphPattern = a:TriplesBlock? _ b:GroupGraphPatternSub_item* {
let mut p = a.map(|v| vec![PartialGraphPattern::Other(GraphPattern::BGP(v))]).unwrap_or_else(|| vec![]);
for v in b {
p.extend_from_slice(&v)
}
let mut filter: Option<Expression> = None;
let mut g = MultiSetPattern::default();
let mut g = GraphPattern::default();
for e in p {
match e {
PartialGraphPattern::Optional(p) => match p {
MultiSetPattern::Filter(f, a2) => {
g = MultiSetPattern::LeftJoin(Box::new(g), a2, f)
GraphPattern::Filter(f, a2) => {
g = GraphPattern::LeftJoin(Box::new(g), a2, f)
}
a => {
g = MultiSetPattern::LeftJoin(Box::new(g), Box::new(a), Literal::from(true).into())
g = GraphPattern::LeftJoin(Box::new(g), Box::new(a), Literal::from(true).into())
}
}
PartialGraphPattern::Minus(p) => {
g = MultiSetPattern::Minus(Box::new(g), Box::new(p))
g = GraphPattern::Minus(Box::new(g), Box::new(p))
}
PartialGraphPattern::Bind(expr, var) => {
g = MultiSetPattern::Extend(Box::new(g), var, expr)
g = GraphPattern::Extend(Box::new(g), var, expr)
}
PartialGraphPattern::Filter(expr) => match filter {
Some(f) => { filter = Some(Expression::AndExpression(Box::new(f), Box::new(expr))) },
@ -256,14 +256,14 @@ GroupGraphPatternSub -> MultiSetPattern = a:TriplesBlock? _ b:GroupGraphPatternS
}
}
match filter {
Some(filter) => MultiSetPattern::Filter(filter, Box::new(g)),
Some(filter) => GraphPattern::Filter(filter, Box::new(g)),
None => g
}
}
GroupGraphPatternSub_item -> Vec<PartialGraphPattern> = a:GraphPatternNotTriples _ ('.' _)? b:TriplesBlock? _ {
let mut result = vec![a];
if let Some(v) = b {
result.push(PartialGraphPattern::Other(MultiSetPattern::BGP(v)));
result.push(PartialGraphPattern::Other(GraphPattern::BGP(v)));
}
result
}
@ -290,13 +290,13 @@ OptionalGraphPattern -> PartialGraphPattern = "OPTIONAL"i _ p:GroupGraphPattern
//[58]
GraphGraphPattern -> PartialGraphPattern = "GRAPH"i _ g:VarOrIri _ p:GroupGraphPattern {
PartialGraphPattern::Other(MultiSetPattern::Graph(g, Box::new(p)))
PartialGraphPattern::Other(GraphPattern::Graph(g, Box::new(p)))
}
//[59]
ServiceGraphPattern -> PartialGraphPattern =
"SERVICE"i _ "SILENT"i _ s:VarOrIri _ p:GroupGraphPattern { PartialGraphPattern::Other(MultiSetPattern::Service(s, Box::new(p), true)) } /
"SERVICE"i _ s:VarOrIri _ p:GroupGraphPattern { PartialGraphPattern::Other(MultiSetPattern::Service(s, Box::new(p), false)) }
"SERVICE"i _ "SILENT"i _ s:VarOrIri _ p:GroupGraphPattern { PartialGraphPattern::Other(GraphPattern::Service(s, Box::new(p), true)) } /
"SERVICE"i _ s:VarOrIri _ p:GroupGraphPattern { PartialGraphPattern::Other(GraphPattern::Service(s, Box::new(p), false)) }
//[60]
Bind -> PartialGraphPattern = "BIND"i _ '(' _ e:Expression _ "AS"i _ v:Var _ ')' {
@ -307,8 +307,8 @@ Bind -> PartialGraphPattern = "BIND"i _ '(' _ e:Expression _ "AS"i _ v:Var _ ')'
InlineData -> PartialGraphPattern = "VALUES"i _ p:DataBlock { PartialGraphPattern::Other(p) }
//[62]
DataBlock -> MultiSetPattern = l:(InlineDataOneVar / InlineDataFull) {
ListPattern::Data(l).into()
DataBlock -> GraphPattern = l:(InlineDataOneVar / InlineDataFull) {
GraphPattern::Data(l).into()
}
//[63]
@ -341,10 +341,10 @@ MinusGraphPattern -> PartialGraphPattern = "MINUS"i _ p: GroupGraphPattern {
//[67]
GroupOrUnionGraphPattern -> PartialGraphPattern = p:GroupOrUnionGraphPattern_item **<1,> ("UNION"i _) {?
not_empty_fold(p.into_iter(), |a, b| {
MultiSetPattern::Union(Box::new(a), Box::new(b))
GraphPattern::Union(Box::new(a), Box::new(b))
}).map(PartialGraphPattern::Other)
}
GroupOrUnionGraphPattern_item -> MultiSetPattern = p:GroupGraphPattern _ { p }
GroupOrUnionGraphPattern_item -> GraphPattern = p:GroupGraphPattern _ { p }
//[68]
Filter -> PartialGraphPattern = "FILTER"i _ c:Constraint {

Loading…
Cancel
Save