Simplifies spargebra basic patterns naming

pull/171/head
Tpt 3 years ago
parent e2bbc29198
commit bc27a298fa
  1. 54
      lib/src/sparql/plan_builder.rs
  2. 62
      lib/src/sparql/update.rs
  3. 126
      spargebra/src/algebra.rs
  4. 171
      spargebra/src/parser.rs
  5. 1
      spargebra/src/query.rs
  6. 358
      spargebra/src/term.rs

@ -768,15 +768,15 @@ impl<'a> PlanBuilder<'a> {
fn pattern_value_from_term_or_variable( fn pattern_value_from_term_or_variable(
&mut self, &mut self,
term_or_variable: &TermOrVariable, term_or_variable: &TermPattern,
variables: &mut Vec<Variable>, variables: &mut Vec<Variable>,
) -> Result<PatternValue, EvaluationError> { ) -> Result<PatternValue, EvaluationError> {
Ok(match term_or_variable { Ok(match term_or_variable {
TermOrVariable::Variable(variable) => { TermPattern::Variable(variable) => {
PatternValue::Variable(variable_key(variables, variable)) PatternValue::Variable(variable_key(variables, variable))
} }
TermOrVariable::NamedNode(node) => PatternValue::Constant(self.build_named_node(node)?), TermPattern::NamedNode(node) => PatternValue::Constant(self.build_named_node(node)?),
TermOrVariable::BlankNode(bnode) => { TermPattern::BlankNode(bnode) => {
PatternValue::Variable(variable_key( PatternValue::Variable(variable_key(
variables, variables,
&Variable { &Variable {
@ -785,22 +785,20 @@ impl<'a> PlanBuilder<'a> {
)) ))
//TODO: very bad hack to convert bnode to variable //TODO: very bad hack to convert bnode to variable
} }
TermOrVariable::Literal(literal) => { TermPattern::Literal(literal) => PatternValue::Constant(self.build_literal(literal)?),
PatternValue::Constant(self.build_literal(literal)?)
}
}) })
} }
fn pattern_value_from_named_node_or_variable( fn pattern_value_from_named_node_or_variable(
&mut self, &mut self,
named_node_or_variable: &NamedNodeOrVariable, named_node_or_variable: &NamedNodePattern,
variables: &mut Vec<Variable>, variables: &mut Vec<Variable>,
) -> Result<PatternValue, EvaluationError> { ) -> Result<PatternValue, EvaluationError> {
Ok(match named_node_or_variable { Ok(match named_node_or_variable {
NamedNodeOrVariable::NamedNode(named_node) => { NamedNodePattern::NamedNode(named_node) => {
PatternValue::Constant(self.build_named_node(named_node)?) PatternValue::Constant(self.build_named_node(named_node)?)
} }
NamedNodeOrVariable::Variable(variable) => { NamedNodePattern::Variable(variable) => {
PatternValue::Variable(variable_key(variables, variable)) PatternValue::Variable(variable_key(variables, variable))
} }
}) })
@ -921,21 +919,21 @@ impl<'a> PlanBuilder<'a> {
fn template_value_from_term_or_variable( fn template_value_from_term_or_variable(
&mut self, &mut self,
term_or_variable: &TermOrVariable, term_or_variable: &TermPattern,
variables: &mut Vec<Variable>, variables: &mut Vec<Variable>,
bnodes: &mut Vec<BlankNode>, bnodes: &mut Vec<BlankNode>,
) -> Result<TripleTemplateValue, EvaluationError> { ) -> Result<TripleTemplateValue, EvaluationError> {
Ok(match term_or_variable { Ok(match term_or_variable {
TermOrVariable::Variable(variable) => { TermPattern::Variable(variable) => {
TripleTemplateValue::Variable(variable_key(variables, variable)) TripleTemplateValue::Variable(variable_key(variables, variable))
} }
TermOrVariable::NamedNode(node) => { TermPattern::NamedNode(node) => {
TripleTemplateValue::Constant(self.build_named_node(node)?) TripleTemplateValue::Constant(self.build_named_node(node)?)
} }
TermOrVariable::BlankNode(bnode) => { TermPattern::BlankNode(bnode) => {
TripleTemplateValue::BlankNode(bnode_key(bnodes, bnode)) TripleTemplateValue::BlankNode(bnode_key(bnodes, bnode))
} }
TermOrVariable::Literal(literal) => { TermPattern::Literal(literal) => {
TripleTemplateValue::Constant(self.build_literal(literal)?) TripleTemplateValue::Constant(self.build_literal(literal)?)
} }
}) })
@ -943,14 +941,14 @@ impl<'a> PlanBuilder<'a> {
fn template_value_from_named_node_or_variable( fn template_value_from_named_node_or_variable(
&mut self, &mut self,
named_node_or_variable: &NamedNodeOrVariable, named_node_or_variable: &NamedNodePattern,
variables: &mut Vec<Variable>, variables: &mut Vec<Variable>,
) -> Result<TripleTemplateValue, EvaluationError> { ) -> Result<TripleTemplateValue, EvaluationError> {
Ok(match named_node_or_variable { Ok(match named_node_or_variable {
NamedNodeOrVariable::Variable(variable) => { NamedNodePattern::Variable(variable) => {
TripleTemplateValue::Variable(variable_key(variables, variable)) TripleTemplateValue::Variable(variable_key(variables, variable))
} }
NamedNodeOrVariable::NamedNode(term) => { NamedNodePattern::NamedNode(term) => {
TripleTemplateValue::Constant(self.build_named_node(term)?) TripleTemplateValue::Constant(self.build_named_node(term)?)
} }
}) })
@ -1126,29 +1124,29 @@ fn count_pattern_binds(
assigned_blank_nodes: &HashSet<&BlankNode>, assigned_blank_nodes: &HashSet<&BlankNode>,
) -> u8 { ) -> u8 {
let mut count = 12; let mut count = 12;
if let TermOrVariable::Variable(v) = &pattern.subject { if let TermPattern::Variable(v) = &pattern.subject {
if !assigned_variables.contains(v) { if !assigned_variables.contains(v) {
count -= 4; count -= 4;
} }
} else if let TermOrVariable::BlankNode(bnode) = &pattern.subject { } else if let TermPattern::BlankNode(bnode) = &pattern.subject {
if !assigned_blank_nodes.contains(bnode) { if !assigned_blank_nodes.contains(bnode) {
count -= 4; count -= 4;
} }
} else { } else {
count -= 1; count -= 1;
} }
if let NamedNodeOrVariable::Variable(v) = &pattern.predicate { if let NamedNodePattern::Variable(v) = &pattern.predicate {
if !assigned_variables.contains(v) { if !assigned_variables.contains(v) {
count -= 4; count -= 4;
} }
} else { } else {
count -= 1; count -= 1;
} }
if let TermOrVariable::Variable(v) = &pattern.object { if let TermPattern::Variable(v) = &pattern.object {
if !assigned_variables.contains(v) { if !assigned_variables.contains(v) {
count -= 4; count -= 4;
} }
} else if let TermOrVariable::BlankNode(bnode) = &pattern.object { } else if let TermPattern::BlankNode(bnode) = &pattern.object {
if !assigned_blank_nodes.contains(bnode) { if !assigned_blank_nodes.contains(bnode) {
count -= 4; count -= 4;
} }
@ -1163,17 +1161,17 @@ fn add_pattern_variables<'a>(
variables: &mut HashSet<&'a Variable>, variables: &mut HashSet<&'a Variable>,
blank_nodes: &mut HashSet<&'a BlankNode>, blank_nodes: &mut HashSet<&'a BlankNode>,
) { ) {
if let TermOrVariable::Variable(v) = &pattern.subject { if let TermPattern::Variable(v) = &pattern.subject {
variables.insert(v); variables.insert(v);
} else if let TermOrVariable::BlankNode(bnode) = &pattern.subject { } else if let TermPattern::BlankNode(bnode) = &pattern.subject {
blank_nodes.insert(bnode); blank_nodes.insert(bnode);
} }
if let NamedNodeOrVariable::Variable(v) = &pattern.predicate { if let NamedNodePattern::Variable(v) = &pattern.predicate {
variables.insert(v); variables.insert(v);
} }
if let TermOrVariable::Variable(v) = &pattern.object { if let TermPattern::Variable(v) = &pattern.object {
variables.insert(v); variables.insert(v);
} else if let TermOrVariable::BlankNode(bnode) = &pattern.object { } else if let TermPattern::BlankNode(bnode) = &pattern.object {
blank_nodes.insert(bnode); blank_nodes.insert(bnode);
} }
} }

@ -16,11 +16,11 @@ use crate::storage::Storage;
use http::header::{ACCEPT, CONTENT_TYPE, USER_AGENT}; use http::header::{ACCEPT, CONTENT_TYPE, USER_AGENT};
use http::{Method, Request, StatusCode}; use http::{Method, Request, StatusCode};
use oxiri::Iri; use oxiri::Iri;
use spargebra::algebra::{GraphPattern, GraphTarget, GroundQuadPattern, QuadPattern}; use spargebra::algebra::{GraphPattern, GraphTarget};
use spargebra::term::{ use spargebra::term::{
BlankNode, GraphName, GraphNameOrVariable, GroundQuad, GroundTerm, GroundTermOrVariable, BlankNode, GraphName, GraphNamePattern, GroundQuad, GroundQuadPattern, GroundTerm,
Literal, NamedNode, NamedNodeOrVariable, NamedOrBlankNode, Quad, Term, TermOrVariable, GroundTermPattern, Literal, NamedNode, NamedNodePattern, NamedOrBlankNode, Quad, QuadPattern,
Variable, Term, TermPattern, Variable,
}; };
use spargebra::GraphUpdateOperation; use spargebra::GraphUpdateOperation;
use std::collections::HashMap; use std::collections::HashMap;
@ -376,36 +376,32 @@ impl<'a> SimpleUpdateEvaluator<'a> {
fn encode_term_or_var_for_insertion( fn encode_term_or_var_for_insertion(
&mut self, &mut self,
term: &TermOrVariable, term: &TermPattern,
variables: &[Variable], variables: &[Variable],
values: &[Option<EncodedTerm>], values: &[Option<EncodedTerm>],
bnodes: &mut HashMap<BlankNode, OxBlankNode>, bnodes: &mut HashMap<BlankNode, OxBlankNode>,
validate: impl FnOnce(&EncodedTerm) -> bool, validate: impl FnOnce(&EncodedTerm) -> bool,
) -> Result<Option<EncodedTerm>, EvaluationError> { ) -> Result<Option<EncodedTerm>, EvaluationError> {
Ok(match term { Ok(match term {
TermOrVariable::NamedNode(term) => Some(self.encode_named_node_for_insertion(term)?), TermPattern::NamedNode(term) => Some(self.encode_named_node_for_insertion(term)?),
TermOrVariable::BlankNode(bnode) => Some( TermPattern::BlankNode(bnode) => Some(
self.storage self.storage
.encode_blank_node(bnodes.entry(bnode.clone()).or_default().as_ref())?, .encode_blank_node(bnodes.entry(bnode.clone()).or_default().as_ref())?,
), ),
TermOrVariable::Literal(term) => Some(self.encode_literal_for_insertion(term)?), TermPattern::Literal(term) => Some(self.encode_literal_for_insertion(term)?),
TermOrVariable::Variable(v) => { TermPattern::Variable(v) => self.lookup_variable(v, variables, values).filter(validate),
self.lookup_variable(v, variables, values).filter(validate)
}
}) })
} }
fn encode_named_node_or_var_for_insertion( fn encode_named_node_or_var_for_insertion(
&mut self, &mut self,
term: &NamedNodeOrVariable, term: &NamedNodePattern,
variables: &[Variable], variables: &[Variable],
values: &[Option<EncodedTerm>], values: &[Option<EncodedTerm>],
) -> Result<Option<EncodedTerm>, EvaluationError> { ) -> Result<Option<EncodedTerm>, EvaluationError> {
Ok(match term { Ok(match term {
NamedNodeOrVariable::NamedNode(term) => { NamedNodePattern::NamedNode(term) => Some(self.encode_named_node_for_insertion(term)?),
Some(self.encode_named_node_for_insertion(term)?) NamedNodePattern::Variable(v) => self
}
NamedNodeOrVariable::Variable(v) => self
.lookup_variable(v, variables, values) .lookup_variable(v, variables, values)
.filter(|value| value.is_named_node()), .filter(|value| value.is_named_node()),
}) })
@ -413,16 +409,14 @@ impl<'a> SimpleUpdateEvaluator<'a> {
fn encode_graph_name_or_var_for_insertion( fn encode_graph_name_or_var_for_insertion(
&mut self, &mut self,
term: &GraphNameOrVariable, term: &GraphNamePattern,
variables: &[Variable], variables: &[Variable],
values: &[Option<EncodedTerm>], values: &[Option<EncodedTerm>],
) -> Result<Option<EncodedTerm>, EvaluationError> { ) -> Result<Option<EncodedTerm>, EvaluationError> {
Ok(match term { Ok(match term {
GraphNameOrVariable::NamedNode(term) => { GraphNamePattern::NamedNode(term) => Some(self.encode_named_node_for_insertion(term)?),
Some(self.encode_named_node_for_insertion(term)?) GraphNamePattern::DefaultGraph => Some(EncodedTerm::DefaultGraph),
} GraphNamePattern::Variable(v) => self
GraphNameOrVariable::DefaultGraph => Some(EncodedTerm::DefaultGraph),
GraphNameOrVariable::Variable(v) => self
.lookup_variable(v, variables, values) .lookup_variable(v, variables, values)
.filter(|value| value.is_named_node()), .filter(|value| value.is_named_node()),
}) })
@ -510,28 +504,26 @@ impl<'a> SimpleUpdateEvaluator<'a> {
fn encode_term_or_var_for_deletion( fn encode_term_or_var_for_deletion(
&self, &self,
term: &GroundTermOrVariable, term: &GroundTermPattern,
variables: &[Variable], variables: &[Variable],
values: &[Option<EncodedTerm>], values: &[Option<EncodedTerm>],
) -> Option<EncodedTerm> { ) -> Option<EncodedTerm> {
match term { match term {
GroundTermOrVariable::NamedNode(term) => { GroundTermPattern::NamedNode(term) => Some(self.encode_named_node_for_deletion(term)),
Some(self.encode_named_node_for_deletion(term)) GroundTermPattern::Literal(term) => Some(self.encode_literal_for_deletion(term)),
} GroundTermPattern::Variable(v) => self.lookup_variable(v, variables, values),
GroundTermOrVariable::Literal(term) => Some(self.encode_literal_for_deletion(term)),
GroundTermOrVariable::Variable(v) => self.lookup_variable(v, variables, values),
} }
} }
fn encode_named_node_or_var_for_deletion( fn encode_named_node_or_var_for_deletion(
&self, &self,
term: &NamedNodeOrVariable, term: &NamedNodePattern,
variables: &[Variable], variables: &[Variable],
values: &[Option<EncodedTerm>], values: &[Option<EncodedTerm>],
) -> Option<EncodedTerm> { ) -> Option<EncodedTerm> {
match term { match term {
NamedNodeOrVariable::NamedNode(term) => Some(self.encode_named_node_for_deletion(term)), NamedNodePattern::NamedNode(term) => Some(self.encode_named_node_for_deletion(term)),
NamedNodeOrVariable::Variable(v) => self NamedNodePattern::Variable(v) => self
.lookup_variable(v, variables, values) .lookup_variable(v, variables, values)
.filter(|v| v.is_named_node()), .filter(|v| v.is_named_node()),
} }
@ -539,14 +531,14 @@ impl<'a> SimpleUpdateEvaluator<'a> {
fn encode_graph_name_or_var_for_deletion( fn encode_graph_name_or_var_for_deletion(
&self, &self,
graph_name: &GraphNameOrVariable, graph_name: &GraphNamePattern,
variables: &[Variable], variables: &[Variable],
values: &[Option<EncodedTerm>], values: &[Option<EncodedTerm>],
) -> Option<EncodedTerm> { ) -> Option<EncodedTerm> {
match graph_name { match graph_name {
GraphNameOrVariable::NamedNode(term) => Some(self.encode_named_node_for_deletion(term)), GraphNamePattern::NamedNode(term) => Some(self.encode_named_node_for_deletion(term)),
GraphNameOrVariable::DefaultGraph => Some(EncodedTerm::DefaultGraph), GraphNamePattern::DefaultGraph => Some(EncodedTerm::DefaultGraph),
GraphNameOrVariable::Variable(v) => self GraphNamePattern::Variable(v) => self
.lookup_variable(v, variables, values) .lookup_variable(v, variables, values)
.filter(|v| v.is_named_node()), .filter(|v| v.is_named_node()),
} }

@ -5,38 +5,6 @@ use crate::term::*;
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::fmt; use std::fmt;
/// A [triple pattern](https://www.w3.org/TR/sparql11-query/#defn_TriplePattern)
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct TriplePattern {
pub subject: TermOrVariable,
pub predicate: NamedNodeOrVariable,
pub object: TermOrVariable,
}
impl TriplePattern {
pub(crate) fn new(
subject: impl Into<TermOrVariable>,
predicate: impl Into<NamedNodeOrVariable>,
object: impl Into<TermOrVariable>,
) -> Self {
Self {
subject: subject.into(),
predicate: predicate.into(),
object: object.into(),
}
}
}
impl fmt::Display for TriplePattern {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"(triple {} {} {})",
self.subject, self.predicate, self.object
)
}
}
pub(crate) struct SparqlTriplePattern<'a>(pub(crate) &'a TriplePattern); pub(crate) struct SparqlTriplePattern<'a>(pub(crate) &'a TriplePattern);
impl<'a> fmt::Display for SparqlTriplePattern<'a> { impl<'a> fmt::Display for SparqlTriplePattern<'a> {
@ -49,81 +17,11 @@ impl<'a> fmt::Display for SparqlTriplePattern<'a> {
} }
} }
/// A [triple pattern](https://www.w3.org/TR/sparql11-query/#defn_TriplePattern) in a specific graph
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct QuadPattern {
pub subject: TermOrVariable,
pub predicate: NamedNodeOrVariable,
pub object: TermOrVariable,
pub graph_name: GraphNameOrVariable,
}
impl QuadPattern {
pub(crate) fn new(
subject: impl Into<TermOrVariable>,
predicate: impl Into<NamedNodeOrVariable>,
object: impl Into<TermOrVariable>,
graph_name: impl Into<GraphNameOrVariable>,
) -> Self {
Self {
subject: subject.into(),
predicate: predicate.into(),
object: object.into(),
graph_name: graph_name.into(),
}
}
}
impl fmt::Display for QuadPattern {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.graph_name == GraphNameOrVariable::DefaultGraph {
write!(
f,
"(triple {} {} {})",
self.subject, self.predicate, self.object
)
} else {
write!(
f,
"(graph {} (triple {} {} {}))",
self.graph_name, self.subject, self.predicate, self.object
)
}
}
}
/// A [triple pattern](https://www.w3.org/TR/sparql11-query/#defn_TriplePattern) in a specific graph without blank nodes
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct GroundQuadPattern {
pub subject: GroundTermOrVariable,
pub predicate: NamedNodeOrVariable,
pub object: GroundTermOrVariable,
pub graph_name: GraphNameOrVariable,
}
impl fmt::Display for GroundQuadPattern {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.graph_name == GraphNameOrVariable::DefaultGraph {
write!(
f,
"(triple {} {} {})",
self.subject, self.predicate, self.object
)
} else {
write!(
f,
"(graph {} (triple {} {} {}))",
self.graph_name, self.subject, self.predicate, self.object
)
}
}
}
pub(crate) struct SparqlQuadPattern<'a>(pub(crate) &'a QuadPattern); pub(crate) struct SparqlQuadPattern<'a>(pub(crate) &'a QuadPattern);
impl<'a> fmt::Display for SparqlQuadPattern<'a> { impl<'a> fmt::Display for SparqlQuadPattern<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.0.graph_name == GraphNameOrVariable::DefaultGraph { if self.0.graph_name == GraphNamePattern::DefaultGraph {
write!( write!(
f, f,
"{} {} {} .", "{} {} {} .",
@ -143,7 +41,7 @@ pub(crate) struct SparqlGroundQuadPattern<'a>(pub(crate) &'a GroundQuadPattern);
impl<'a> fmt::Display for SparqlGroundQuadPattern<'a> { impl<'a> fmt::Display for SparqlGroundQuadPattern<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.0.graph_name == GraphNameOrVariable::DefaultGraph { if self.0.graph_name == GraphNamePattern::DefaultGraph {
write!( write!(
f, f,
"{} {} {} .", "{} {} {} .",
@ -570,9 +468,9 @@ pub enum GraphPattern {
Bgp(Vec<TriplePattern>), Bgp(Vec<TriplePattern>),
/// A [property path pattern](https://www.w3.org/TR/sparql11-query/#defn_evalPP_predicate) /// A [property path pattern](https://www.w3.org/TR/sparql11-query/#defn_evalPP_predicate)
Path { Path {
subject: TermOrVariable, subject: TermPattern,
path: PropertyPathExpression, path: PropertyPathExpression,
object: TermOrVariable, object: TermPattern,
}, },
/// [Join](https://www.w3.org/TR/sparql11-query/#defn_algJoin) /// [Join](https://www.w3.org/TR/sparql11-query/#defn_algJoin)
Join { Join {
@ -596,7 +494,7 @@ pub enum GraphPattern {
right: Box<GraphPattern>, right: Box<GraphPattern>,
}, },
Graph { Graph {
graph_name: NamedNodeOrVariable, graph_name: NamedNodePattern,
inner: Box<GraphPattern>, inner: Box<GraphPattern>,
}, },
/// [Extend](https://www.w3.org/TR/sparql11-query/#defn_extend) /// [Extend](https://www.w3.org/TR/sparql11-query/#defn_extend)
@ -643,7 +541,7 @@ pub enum GraphPattern {
}, },
/// [Service](https://www.w3.org/TR/sparql11-federated-query/#defn_evalService) /// [Service](https://www.w3.org/TR/sparql11-federated-query/#defn_evalService)
Service { Service {
name: NamedNodeOrVariable, name: NamedNodePattern,
pattern: Box<GraphPattern>, pattern: Box<GraphPattern>,
silent: bool, silent: bool,
}, },
@ -783,13 +681,13 @@ impl GraphPattern {
match self { match self {
GraphPattern::Bgp(p) => { GraphPattern::Bgp(p) => {
for pattern in p { for pattern in p {
if let TermOrVariable::Variable(s) = &pattern.subject { if let TermPattern::Variable(s) = &pattern.subject {
vars.insert(s); vars.insert(s);
} }
if let NamedNodeOrVariable::Variable(p) = &pattern.predicate { if let NamedNodePattern::Variable(p) = &pattern.predicate {
vars.insert(p); vars.insert(p);
} }
if let TermOrVariable::Variable(o) = &pattern.object { if let TermPattern::Variable(o) = &pattern.object {
vars.insert(o); vars.insert(o);
} }
} }
@ -797,10 +695,10 @@ impl GraphPattern {
GraphPattern::Path { GraphPattern::Path {
subject, object, .. subject, object, ..
} => { } => {
if let TermOrVariable::Variable(s) = subject { if let TermPattern::Variable(s) = subject {
vars.insert(s); vars.insert(s);
} }
if let TermOrVariable::Variable(o) = object { if let TermPattern::Variable(o) = object {
vars.insert(o); vars.insert(o);
} }
} }
@ -812,7 +710,7 @@ impl GraphPattern {
} }
GraphPattern::Filter { inner, .. } => inner.add_visible_variables(vars), GraphPattern::Filter { inner, .. } => inner.add_visible_variables(vars),
GraphPattern::Graph { graph_name, inner } => { GraphPattern::Graph { graph_name, inner } => {
if let NamedNodeOrVariable::Variable(ref g) = graph_name { if let NamedNodePattern::Variable(ref g) = graph_name {
vars.insert(g); vars.insert(g);
} }
inner.add_visible_variables(vars); inner.add_visible_variables(vars);

@ -139,9 +139,9 @@ impl From<PropertyPathExpression> for VariableOrPropertyPath {
} }
fn add_to_triple_or_path_patterns( fn add_to_triple_or_path_patterns(
subject: TermOrVariable, subject: TermPattern,
predicate: impl Into<VariableOrPropertyPath>, predicate: impl Into<VariableOrPropertyPath>,
object: TermOrVariable, object: TermPattern,
patterns: &mut Vec<TripleOrPathPattern>, patterns: &mut Vec<TripleOrPathPattern>,
) { ) {
match predicate.into() { match predicate.into() {
@ -199,9 +199,9 @@ fn build_bgp(patterns: Vec<TripleOrPathPattern>) -> GraphPattern {
enum TripleOrPathPattern { enum TripleOrPathPattern {
Triple(TriplePattern), Triple(TriplePattern),
Path { Path {
subject: TermOrVariable, subject: TermPattern,
path: PropertyPathExpression, path: PropertyPathExpression,
object: TermOrVariable, object: TermPattern,
}, },
} }
@ -454,10 +454,7 @@ fn build_select(
m m
} }
fn copy_graph( fn copy_graph(from: impl Into<GraphName>, to: impl Into<GraphNamePattern>) -> GraphUpdateOperation {
from: impl Into<GraphName>,
to: impl Into<GraphNameOrVariable>,
) -> GraphUpdateOperation {
let bgp = GraphPattern::Bgp(vec![TriplePattern::new( let bgp = GraphPattern::Bgp(vec![TriplePattern::new(
Variable { name: "s".into() }, Variable { name: "s".into() },
Variable { name: "p".into() }, Variable { name: "p".into() },
@ -840,14 +837,14 @@ parser! {
pattern: build_select(Selection { pattern: build_select(Selection {
option: SelectionOption::Default, option: SelectionOption::Default,
variables: Some(p.into_iter().map(|var_or_iri| match var_or_iri { variables: Some(p.into_iter().map(|var_or_iri| match var_or_iri {
NamedNodeOrVariable::NamedNode(n) => SelectionMember::Expression(n.into(), variable()), NamedNodePattern::NamedNode(n) => SelectionMember::Expression(n.into(), variable()),
NamedNodeOrVariable::Variable(v) => SelectionMember::Variable(v) NamedNodePattern::Variable(v) => SelectionMember::Variable(v)
}).collect()) }).collect())
}, w.unwrap_or_else(GraphPattern::default), g, h, o, l, v, state), }, w.unwrap_or_else(GraphPattern::default), g, h, o, l, v, state),
base_iri: state.base_iri.clone() base_iri: state.base_iri.clone()
} }
} }
rule DescribeQuery_item() -> NamedNodeOrVariable = i:VarOrIri() _ { i } rule DescribeQuery_item() -> NamedNodePattern = i:VarOrIri() _ { i }
//[12] //[12]
rule AskQuery() -> Query = i("ASK") _ d:DatasetClauses() w:WhereClause() _ g:GroupClause()? _ h:HavingClause()? _ o:OrderClause()? _ l:LimitOffsetClauses()? _ v:ValuesClause() { rule AskQuery() -> Query = i("ASK") _ d:DatasetClauses() w:WhereClause() _ g:GroupClause()? _ h:HavingClause()? _ o:OrderClause()? _ l:LimitOffsetClauses()? _ v:ValuesClause() {
@ -1037,24 +1034,24 @@ parser! {
let pattern = d.iter().map(|q| { let pattern = d.iter().map(|q| {
let bgp = GraphPattern::Bgp(vec![TriplePattern::new(q.subject.clone(), q.predicate.clone(), q.object.clone())]); let bgp = GraphPattern::Bgp(vec![TriplePattern::new(q.subject.clone(), q.predicate.clone(), q.object.clone())]);
match &q.graph_name { match &q.graph_name {
GraphNameOrVariable::NamedNode(graph_name) => GraphPattern::Graph { graph_name: graph_name.clone().into(), inner: Box::new(bgp) }, GraphNamePattern::NamedNode(graph_name) => GraphPattern::Graph { graph_name: graph_name.clone().into(), inner: Box::new(bgp) },
GraphNameOrVariable::DefaultGraph => bgp, GraphNamePattern::DefaultGraph => bgp,
GraphNameOrVariable::Variable(graph_name) => GraphPattern::Graph { graph_name: graph_name.clone().into(), inner: Box::new(bgp) }, GraphNamePattern::Variable(graph_name) => GraphPattern::Graph { graph_name: graph_name.clone().into(), inner: Box::new(bgp) },
} }
}).fold(GraphPattern::Bgp(Vec::new()), new_join); }).fold(GraphPattern::Bgp(Vec::new()), new_join);
let delete = d.into_iter().map(|q| Ok(GroundQuadPattern { let delete = d.into_iter().map(|q| Ok(GroundQuadPattern {
subject: match q.subject { subject: match q.subject {
TermOrVariable::NamedNode(subject) => subject.into(), TermPattern::NamedNode(subject) => subject.into(),
TermOrVariable::BlankNode(_) => return Err("Blank nodes are not allowed in DELETE WHERE"), TermPattern::BlankNode(_) => return Err("Blank nodes are not allowed in DELETE WHERE"),
TermOrVariable::Literal(subject) => subject.into(), TermPattern::Literal(subject) => subject.into(),
TermOrVariable::Variable(subject) => subject.into(), TermPattern::Variable(subject) => subject.into(),
}, },
predicate: q.predicate, predicate: q.predicate,
object: match q.object { object: match q.object {
TermOrVariable::NamedNode(object) => object.into(), TermPattern::NamedNode(object) => object.into(),
TermOrVariable::BlankNode(_) => return Err("Blank nodes are not allowed in DELETE WHERE"), TermPattern::BlankNode(_) => return Err("Blank nodes are not allowed in DELETE WHERE"),
TermOrVariable::Literal(object) => object.into(), TermPattern::Literal(object) => object.into(),
TermOrVariable::Variable(object) => object.into(), TermPattern::Variable(object) => object.into(),
}, },
graph_name: q.graph_name graph_name: q.graph_name
})).collect::<Result<Vec<_>,_>>()?; })).collect::<Result<Vec<_>,_>>()?;
@ -1091,7 +1088,7 @@ parser! {
if let Some(with) = with { if let Some(with) = with {
// We inject WITH everywhere // We inject WITH everywhere
delete = delete.into_iter().map(|q| if q.graph_name == GraphNameOrVariable::DefaultGraph { delete = delete.into_iter().map(|q| if q.graph_name == GraphNamePattern::DefaultGraph {
GroundQuadPattern { GroundQuadPattern {
subject: q.subject, subject: q.subject,
predicate: q.predicate, predicate: q.predicate,
@ -1101,7 +1098,7 @@ parser! {
} else { } else {
q q
}).collect(); }).collect();
insert = insert.into_iter().map(|q| if q.graph_name == GraphNameOrVariable::DefaultGraph { insert = insert.into_iter().map(|q| if q.graph_name == GraphNamePattern::DefaultGraph {
QuadPattern { QuadPattern {
subject: q.subject, subject: q.subject,
predicate: q.predicate, predicate: q.predicate,
@ -1138,17 +1135,17 @@ parser! {
rule DeleteClause() -> Vec<GroundQuadPattern> = i("DELETE") _ q:QuadPattern() {? rule DeleteClause() -> Vec<GroundQuadPattern> = i("DELETE") _ q:QuadPattern() {?
q.into_iter().map(|q| Ok(GroundQuadPattern { q.into_iter().map(|q| Ok(GroundQuadPattern {
subject: match q.subject { subject: match q.subject {
TermOrVariable::NamedNode(subject) => subject.into(), TermPattern::NamedNode(subject) => subject.into(),
TermOrVariable::BlankNode(_) => return Err("Blank nodes are not allowed in DELETE WHERE"), TermPattern::BlankNode(_) => return Err("Blank nodes are not allowed in DELETE WHERE"),
TermOrVariable::Literal(subject) => subject.into(), TermPattern::Literal(subject) => subject.into(),
TermOrVariable::Variable(subject) => subject.into(), TermPattern::Variable(subject) => subject.into(),
}, },
predicate: q.predicate, predicate: q.predicate,
object: match q.object { object: match q.object {
TermOrVariable::NamedNode(object) => object.into(), TermPattern::NamedNode(object) => object.into(),
TermOrVariable::BlankNode(_) => return Err("Blank nodes are not allowed in DELETE WHERE"), TermPattern::BlankNode(_) => return Err("Blank nodes are not allowed in DELETE WHERE"),
TermOrVariable::Literal(object) => object.into(), TermPattern::Literal(object) => object.into(),
TermOrVariable::Variable(object) => object.into(), TermPattern::Variable(object) => object.into(),
}, },
graph_name: q.graph_name graph_name: q.graph_name
})).collect::<Result<Vec<_>,_>>() })).collect::<Result<Vec<_>,_>>()
@ -1189,49 +1186,49 @@ parser! {
rule QuadData() -> Vec<Quad> = "{" _ q:Quads() _ "}" {? rule QuadData() -> Vec<Quad> = "{" _ q:Quads() _ "}" {?
q.into_iter().map(|q| Ok(Quad { q.into_iter().map(|q| Ok(Quad {
subject: match q.subject { subject: match q.subject {
TermOrVariable::NamedNode(t) => t.into(), TermPattern::NamedNode(t) => t.into(),
TermOrVariable::BlankNode(t) => t.into(), TermPattern::BlankNode(t) => t.into(),
TermOrVariable::Literal(_) | TermOrVariable::Variable(_) => return Err(()) TermPattern::Literal(_) | TermPattern::Variable(_) => return Err(())
}, },
predicate: if let NamedNodeOrVariable::NamedNode(t) = q.predicate { predicate: if let NamedNodePattern::NamedNode(t) = q.predicate {
t t
} else { } else {
return Err(()) return Err(())
}, },
object: match q.object { object: match q.object {
TermOrVariable::NamedNode(t) => t.into(), TermPattern::NamedNode(t) => t.into(),
TermOrVariable::BlankNode(t) => t.into(), TermPattern::BlankNode(t) => t.into(),
TermOrVariable::Literal(t) => t.into(), TermPattern::Literal(t) => t.into(),
TermOrVariable::Variable(_) => return Err(()) TermPattern::Variable(_) => return Err(())
}, },
graph_name: match q.graph_name { graph_name: match q.graph_name {
GraphNameOrVariable::NamedNode(t) => t.into(), GraphNamePattern::NamedNode(t) => t.into(),
GraphNameOrVariable::DefaultGraph => GraphName::DefaultGraph, GraphNamePattern::DefaultGraph => GraphName::DefaultGraph,
GraphNameOrVariable::Variable(_) => return Err(()) GraphNamePattern::Variable(_) => return Err(())
} }
})).collect::<Result<Vec<_>, ()>>().map_err(|_| "Variables are not allowed in INSERT DATA and DELETE DATA") })).collect::<Result<Vec<_>, ()>>().map_err(|_| "Variables are not allowed in INSERT DATA and DELETE DATA")
} }
rule GroundQuadData() -> Vec<GroundQuad> = "{" _ q:Quads() _ "}" {? rule GroundQuadData() -> Vec<GroundQuad> = "{" _ q:Quads() _ "}" {?
q.into_iter().map(|q| Ok(GroundQuad { q.into_iter().map(|q| Ok(GroundQuad {
subject: if let TermOrVariable::NamedNode(t) = q.subject { subject: if let TermPattern::NamedNode(t) = q.subject {
t t
} else { } else {
return Err(()) return Err(())
}, },
predicate: if let NamedNodeOrVariable::NamedNode(t) = q.predicate { predicate: if let NamedNodePattern::NamedNode(t) = q.predicate {
t t
} else { } else {
return Err(()) return Err(())
}, },
object: match q.object { object: match q.object {
TermOrVariable::NamedNode(t) => t.into(), TermPattern::NamedNode(t) => t.into(),
TermOrVariable::Literal(t) => t.into(), TermPattern::Literal(t) => t.into(),
TermOrVariable::BlankNode(_) | TermOrVariable::Variable(_) => return Err(()) TermPattern::BlankNode(_) | TermPattern::Variable(_) => return Err(())
}, },
graph_name: match q.graph_name { graph_name: match q.graph_name {
GraphNameOrVariable::NamedNode(t) => t.into(), GraphNamePattern::NamedNode(t) => t.into(),
GraphNameOrVariable::DefaultGraph => GraphName::DefaultGraph, GraphNamePattern::DefaultGraph => GraphName::DefaultGraph,
GraphNameOrVariable::Variable(_) => return Err(()) GraphNamePattern::Variable(_) => return Err(())
} }
})).collect::<Result<Vec<_>, ()>>().map_err(|_| "Variables are not allowed in INSERT DATA and DELETE DATA") })).collect::<Result<Vec<_>, ()>>().map_err(|_| "Variables are not allowed in INSERT DATA and DELETE DATA")
} }
@ -1241,7 +1238,7 @@ parser! {
q.into_iter().flatten().collect() q.into_iter().flatten().collect()
} }
rule Quads_TriplesTemplate() -> Vec<QuadPattern> = t:TriplesTemplate() { rule Quads_TriplesTemplate() -> Vec<QuadPattern> = t:TriplesTemplate() {
t.into_iter().map(|t| QuadPattern::new(t.subject, t.predicate, t.object, GraphNameOrVariable::DefaultGraph)).collect() t.into_iter().map(|t| QuadPattern::new(t.subject, t.predicate, t.object, GraphNamePattern::DefaultGraph)).collect()
} //TODO: return iter? } //TODO: return iter?
rule Quads_QuadsNotTriples() -> Vec<QuadPattern> = q:QuadsNotTriples() _ "."? { q } rule Quads_QuadsNotTriples() -> Vec<QuadPattern> = q:QuadsNotTriples() _ "."? { q }
@ -1452,19 +1449,19 @@ parser! {
} }
//[76] //[76]
rule PropertyList() -> FocusedTriplePattern<Vec<(NamedNodeOrVariable,Vec<TermOrVariable>)>> = rule PropertyList() -> FocusedTriplePattern<Vec<(NamedNodePattern,Vec<TermPattern>)>> =
PropertyListNotEmpty() / PropertyListNotEmpty() /
{ FocusedTriplePattern::default() } { FocusedTriplePattern::default() }
//[77] //[77]
rule PropertyListNotEmpty() -> FocusedTriplePattern<Vec<(NamedNodeOrVariable,Vec<TermOrVariable>)>> = l:PropertyListNotEmpty_item() **<1,> (";" _) { rule PropertyListNotEmpty() -> FocusedTriplePattern<Vec<(NamedNodePattern,Vec<TermPattern>)>> = l:PropertyListNotEmpty_item() **<1,> (";" _) {
l.into_iter().fold(FocusedTriplePattern::<Vec<(NamedNodeOrVariable,Vec<TermOrVariable>)>>::default(), |mut a, b| { l.into_iter().fold(FocusedTriplePattern::<Vec<(NamedNodePattern,Vec<TermPattern>)>>::default(), |mut a, b| {
a.focus.push(b.focus); a.focus.push(b.focus);
a.patterns.extend(b.patterns); a.patterns.extend(b.patterns);
a a
}) })
} }
rule PropertyListNotEmpty_item() -> FocusedTriplePattern<(NamedNodeOrVariable,Vec<TermOrVariable>)> = p:Verb() _ o:ObjectList() _ { rule PropertyListNotEmpty_item() -> FocusedTriplePattern<(NamedNodePattern,Vec<TermPattern>)> = p:Verb() _ o:ObjectList() _ {
FocusedTriplePattern { FocusedTriplePattern {
focus: (p, o.focus), focus: (p, o.focus),
patterns: o.patterns patterns: o.patterns
@ -1472,20 +1469,20 @@ parser! {
} }
//[78] //[78]
rule Verb() -> NamedNodeOrVariable = VarOrIri() / "a" { iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#type").into() } rule Verb() -> NamedNodePattern = VarOrIri() / "a" { iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#type").into() }
//[79] //[79]
rule ObjectList() -> FocusedTriplePattern<Vec<TermOrVariable>> = o:ObjectList_item() **<1,> ("," _) { rule ObjectList() -> FocusedTriplePattern<Vec<TermPattern>> = o:ObjectList_item() **<1,> ("," _) {
o.into_iter().fold(FocusedTriplePattern::<Vec<TermOrVariable>>::default(), |mut a, b| { o.into_iter().fold(FocusedTriplePattern::<Vec<TermPattern>>::default(), |mut a, b| {
a.focus.push(b.focus); a.focus.push(b.focus);
a.patterns.extend_from_slice(&b.patterns); a.patterns.extend_from_slice(&b.patterns);
a a
}) })
} }
rule ObjectList_item() -> FocusedTriplePattern<TermOrVariable> = o:Object() _ { o } rule ObjectList_item() -> FocusedTriplePattern<TermPattern> = o:Object() _ { o }
//[80] //[80]
rule Object() -> FocusedTriplePattern<TermOrVariable> = GraphNode() rule Object() -> FocusedTriplePattern<TermPattern> = GraphNode()
//[81] //[81]
rule TriplesSameSubjectPath() -> Vec<TripleOrPathPattern> = rule TriplesSameSubjectPath() -> Vec<TripleOrPathPattern> =
@ -1510,12 +1507,12 @@ parser! {
} }
//[82] //[82]
rule PropertyListPath() -> FocusedTripleOrPathPattern<Vec<(VariableOrPropertyPath,Vec<TermOrVariable>)>> = rule PropertyListPath() -> FocusedTripleOrPathPattern<Vec<(VariableOrPropertyPath,Vec<TermPattern>)>> =
PropertyListPathNotEmpty() / PropertyListPathNotEmpty() /
{ FocusedTripleOrPathPattern::default() } { FocusedTripleOrPathPattern::default() }
//[83] //[83]
rule PropertyListPathNotEmpty() -> FocusedTripleOrPathPattern<Vec<(VariableOrPropertyPath,Vec<TermOrVariable>)>> = hp:(VerbPath() / VerbSimple()) _ ho:ObjectListPath() _ t:PropertyListPathNotEmpty_item()* { rule PropertyListPathNotEmpty() -> FocusedTripleOrPathPattern<Vec<(VariableOrPropertyPath,Vec<TermPattern>)>> = hp:(VerbPath() / VerbSimple()) _ ho:ObjectListPath() _ t:PropertyListPathNotEmpty_item()* {
t.into_iter().flat_map(|e| e.into_iter()).fold(FocusedTripleOrPathPattern { t.into_iter().flat_map(|e| e.into_iter()).fold(FocusedTripleOrPathPattern {
focus: vec![(hp, ho.focus)], focus: vec![(hp, ho.focus)],
patterns: ho.patterns patterns: ho.patterns
@ -1525,10 +1522,10 @@ parser! {
a a
}) })
} }
rule PropertyListPathNotEmpty_item() -> Option<FocusedTriplePattern<(VariableOrPropertyPath,Vec<TermOrVariable>)>> = ";" _ c:PropertyListPathNotEmpty_item_content()? { rule PropertyListPathNotEmpty_item() -> Option<FocusedTriplePattern<(VariableOrPropertyPath,Vec<TermPattern>)>> = ";" _ c:PropertyListPathNotEmpty_item_content()? {
c c
} }
rule PropertyListPathNotEmpty_item_content() -> FocusedTriplePattern<(VariableOrPropertyPath,Vec<TermOrVariable>)> = p:(VerbPath() / VerbSimple()) _ o:ObjectList() _ { rule PropertyListPathNotEmpty_item_content() -> FocusedTriplePattern<(VariableOrPropertyPath,Vec<TermPattern>)> = p:(VerbPath() / VerbSimple()) _ o:ObjectList() _ {
FocusedTriplePattern { FocusedTriplePattern {
focus: (p, o.focus), focus: (p, o.focus),
patterns: o.patterns patterns: o.patterns
@ -1546,17 +1543,17 @@ parser! {
} }
//[86] //[86]
rule ObjectListPath() -> FocusedTripleOrPathPattern<Vec<TermOrVariable>> = o:ObjectPath_item() **<1,> ("," _) { rule ObjectListPath() -> FocusedTripleOrPathPattern<Vec<TermPattern>> = o:ObjectPath_item() **<1,> ("," _) {
o.into_iter().fold(FocusedTripleOrPathPattern::<Vec<TermOrVariable>>::default(), |mut a, b| { o.into_iter().fold(FocusedTripleOrPathPattern::<Vec<TermPattern>>::default(), |mut a, b| {
a.focus.push(b.focus); a.focus.push(b.focus);
a.patterns.extend(b.patterns); a.patterns.extend(b.patterns);
a a
}) })
} }
rule ObjectPath_item() -> FocusedTripleOrPathPattern<TermOrVariable> = o:ObjectPath() _ { o } rule ObjectPath_item() -> FocusedTripleOrPathPattern<TermPattern> = o:ObjectPath() _ { o }
//[87] //[87]
rule ObjectPath() -> FocusedTripleOrPathPattern<TermOrVariable> = GraphNodePath() rule ObjectPath() -> FocusedTripleOrPathPattern<TermPattern> = GraphNodePath()
//[88] //[88]
rule Path() -> PropertyPathExpression = PathAlternative() rule Path() -> PropertyPathExpression = PathAlternative()
@ -1634,12 +1631,12 @@ parser! {
"a" { Either::Left(iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")) } "a" { Either::Left(iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")) }
//[98] //[98]
rule TriplesNode() -> FocusedTriplePattern<TermOrVariable> = Collection() / BlankNodePropertyList() rule TriplesNode() -> FocusedTriplePattern<TermPattern> = Collection() / BlankNodePropertyList()
//[99] //[99]
rule BlankNodePropertyList() -> FocusedTriplePattern<TermOrVariable> = "[" _ po:PropertyListNotEmpty() _ "]" { rule BlankNodePropertyList() -> FocusedTriplePattern<TermPattern> = "[" _ po:PropertyListNotEmpty() _ "]" {
let mut patterns: Vec<TriplePattern> = Vec::default(); let mut patterns: Vec<TriplePattern> = Vec::default();
let mut bnode = TermOrVariable::from(bnode()); let mut bnode = TermPattern::from(bnode());
for (p, os) in po.focus { for (p, os) in po.focus {
for o in os { for o in os {
patterns.push(TriplePattern::new(bnode.clone(), p.clone(), o)); patterns.push(TriplePattern::new(bnode.clone(), p.clone(), o));
@ -1652,12 +1649,12 @@ parser! {
} }
//[100] //[100]
rule TriplesNodePath() -> FocusedTripleOrPathPattern<TermOrVariable> = CollectionPath() / BlankNodePropertyListPath() rule TriplesNodePath() -> FocusedTripleOrPathPattern<TermPattern> = CollectionPath() / BlankNodePropertyListPath()
//[101] //[101]
rule BlankNodePropertyListPath() -> FocusedTripleOrPathPattern<TermOrVariable> = "[" _ po:PropertyListPathNotEmpty() _ "]" { rule BlankNodePropertyListPath() -> FocusedTripleOrPathPattern<TermPattern> = "[" _ po:PropertyListPathNotEmpty() _ "]" {
let mut patterns: Vec<TripleOrPathPattern> = Vec::default(); let mut patterns: Vec<TripleOrPathPattern> = Vec::default();
let mut bnode = TermOrVariable::from(bnode()); let mut bnode = TermPattern::from(bnode());
for (p, os) in po.focus { for (p, os) in po.focus {
for o in os { for o in os {
add_to_triple_or_path_patterns(bnode.clone(), p.clone(), o, &mut patterns); add_to_triple_or_path_patterns(bnode.clone(), p.clone(), o, &mut patterns);
@ -1670,11 +1667,11 @@ parser! {
} }
//[102] //[102]
rule Collection() -> FocusedTriplePattern<TermOrVariable> = "(" _ o:Collection_item()+ ")" { rule Collection() -> FocusedTriplePattern<TermPattern> = "(" _ o:Collection_item()+ ")" {
let mut patterns: Vec<TriplePattern> = Vec::default(); let mut patterns: Vec<TriplePattern> = Vec::default();
let mut current_list_node = TermOrVariable::from(iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil")); let mut current_list_node = TermPattern::from(iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"));
for objWithPatterns in o.into_iter().rev() { for objWithPatterns in o.into_iter().rev() {
let new_blank_node = TermOrVariable::from(bnode()); let new_blank_node = TermPattern::from(bnode());
patterns.push(TriplePattern::new(new_blank_node.clone(), iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#first"), objWithPatterns.focus.clone())); patterns.push(TriplePattern::new(new_blank_node.clone(), iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#first"), objWithPatterns.focus.clone()));
patterns.push(TriplePattern::new(new_blank_node.clone(), iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"), current_list_node)); patterns.push(TriplePattern::new(new_blank_node.clone(), iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"), current_list_node));
current_list_node = new_blank_node; current_list_node = new_blank_node;
@ -1685,14 +1682,14 @@ parser! {
patterns patterns
} }
} }
rule Collection_item() -> FocusedTriplePattern<TermOrVariable> = o:GraphNode() _ { o } rule Collection_item() -> FocusedTriplePattern<TermPattern> = o:GraphNode() _ { o }
//[103] //[103]
rule CollectionPath() -> FocusedTripleOrPathPattern<TermOrVariable> = "(" _ o:CollectionPath_item()+ _ ")" { rule CollectionPath() -> FocusedTripleOrPathPattern<TermPattern> = "(" _ o:CollectionPath_item()+ _ ")" {
let mut patterns: Vec<TripleOrPathPattern> = Vec::default(); let mut patterns: Vec<TripleOrPathPattern> = Vec::default();
let mut current_list_node = TermOrVariable::from(iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil")); let mut current_list_node = TermPattern::from(iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"));
for objWithPatterns in o.into_iter().rev() { for objWithPatterns in o.into_iter().rev() {
let new_blank_node = TermOrVariable::from(bnode()); let new_blank_node = TermPattern::from(bnode());
patterns.push(TriplePattern::new(new_blank_node.clone(), iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#first"), objWithPatterns.focus.clone()).into()); patterns.push(TriplePattern::new(new_blank_node.clone(), iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#first"), objWithPatterns.focus.clone()).into());
patterns.push(TriplePattern::new(new_blank_node.clone(), iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"), current_list_node).into()); patterns.push(TriplePattern::new(new_blank_node.clone(), iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"), current_list_node).into());
current_list_node = new_blank_node; current_list_node = new_blank_node;
@ -1703,25 +1700,25 @@ parser! {
patterns patterns
} }
} }
rule CollectionPath_item() -> FocusedTripleOrPathPattern<TermOrVariable> = p:GraphNodePath() _ { p } rule CollectionPath_item() -> FocusedTripleOrPathPattern<TermPattern> = p:GraphNodePath() _ { p }
//[104] //[104]
rule GraphNode() -> FocusedTriplePattern<TermOrVariable> = rule GraphNode() -> FocusedTriplePattern<TermPattern> =
t:VarOrTerm() { FocusedTriplePattern::new(t) } / t:VarOrTerm() { FocusedTriplePattern::new(t) } /
TriplesNode() TriplesNode()
//[105] //[105]
rule GraphNodePath() -> FocusedTripleOrPathPattern<TermOrVariable> = rule GraphNodePath() -> FocusedTripleOrPathPattern<TermPattern> =
t:VarOrTerm() { FocusedTripleOrPathPattern::new(t) } / t:VarOrTerm() { FocusedTripleOrPathPattern::new(t) } /
TriplesNodePath() TriplesNodePath()
//[106] //[106]
rule VarOrTerm() -> TermOrVariable = rule VarOrTerm() -> TermPattern =
v:Var() { v.into() } / v:Var() { v.into() } /
t:GraphTerm() { t.into() } t:GraphTerm() { t.into() }
//[107] //[107]
rule VarOrIri() -> NamedNodeOrVariable = rule VarOrIri() -> NamedNodePattern =
v:Var() { v.into() } / v:Var() { v.into() } /
i:iri() { i.into() } i:iri() { i.into() }

@ -1,5 +1,6 @@
use crate::algebra::*; use crate::algebra::*;
use crate::parser::{parse_query, ParseError}; use crate::parser::{parse_query, ParseError};
use crate::term::*;
use oxiri::Iri; use oxiri::Iri;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fmt; use std::fmt;

@ -119,28 +119,6 @@ impl fmt::Display for Literal {
} }
} }
/// A [SPARQL query variable](https://www.w3.org/TR/sparql11-query/#sparqlQueryVariables).
///
/// ```
/// use spargebra::term::Variable;
///
/// assert_eq!(
/// "?foo",
/// Variable { name: "foo".into() }.to_string()
/// );
/// ```
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)]
pub struct Variable {
pub name: String,
}
impl fmt::Display for Variable {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "?{}", self.name)
}
}
/// The union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) and [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node). /// The union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) and [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node).
/// ///
/// The default string formatter is returning an N-Triples, Turtle and SPARQL compatible representation. /// The default string formatter is returning an N-Triples, Turtle and SPARQL compatible representation.
@ -174,39 +152,6 @@ impl From<BlankNode> for NamedOrBlankNode {
} }
} }
/// The union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) and [literals](https://www.w3.org/TR/rdf11-concepts/#dfn-literal).
///
/// The default string formatter is returning an N-Triples, Turtle and SPARQL compatible representation.
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum GroundTerm {
NamedNode(NamedNode),
Literal(Literal),
}
impl fmt::Display for GroundTerm {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
GroundTerm::NamedNode(node) => node.fmt(f),
GroundTerm::Literal(literal) => literal.fmt(f),
}
}
}
impl From<NamedNode> for GroundTerm {
#[inline]
fn from(node: NamedNode) -> Self {
Self::NamedNode(node)
}
}
impl From<Literal> for GroundTerm {
#[inline]
fn from(literal: Literal) -> Self {
Self::Literal(literal)
}
}
/// An RDF [term](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-term). /// An RDF [term](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-term).
/// ///
/// It is the union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri), [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) and [literals](https://www.w3.org/TR/rdf11-concepts/#dfn-literal). /// It is the union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri), [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) and [literals](https://www.w3.org/TR/rdf11-concepts/#dfn-literal).
@ -261,8 +206,42 @@ impl From<NamedOrBlankNode> for Term {
} }
} }
/// The union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) and [literals](https://www.w3.org/TR/rdf11-concepts/#dfn-literal).
///
/// The default string formatter is returning an N-Triples, Turtle and SPARQL compatible representation.
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum GroundTerm {
NamedNode(NamedNode),
Literal(Literal),
}
impl fmt::Display for GroundTerm {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
GroundTerm::NamedNode(node) => node.fmt(f),
GroundTerm::Literal(literal) => literal.fmt(f),
}
}
}
impl From<NamedNode> for GroundTerm {
#[inline]
fn from(node: NamedNode) -> Self {
Self::NamedNode(node)
}
}
impl From<Literal> for GroundTerm {
#[inline]
fn from(literal: Literal) -> Self {
Self::Literal(literal)
}
}
/// A possible graph name. /// A possible graph name.
/// It is the union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri), [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node), and the [default graph name](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph). ///
/// It is the union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) and the [default graph name](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph).
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum GraphName { pub enum GraphName {
NamedNode(NamedNode), NamedNode(NamedNode),
@ -368,29 +347,54 @@ impl fmt::Display for GroundQuad {
} }
} }
/// A [SPARQL query variable](https://www.w3.org/TR/sparql11-query/#sparqlQueryVariables).
///
/// ```
/// use spargebra::term::Variable;
///
/// assert_eq!(
/// "?foo",
/// Variable { name: "foo".into() }.to_string()
/// );
/// ```
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)]
pub struct Variable {
pub name: String,
}
impl fmt::Display for Variable {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "?{}", self.name)
}
}
/// The union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) and [variables](https://www.w3.org/TR/sparql11-query/#sparqlQueryVariables). /// The union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) and [variables](https://www.w3.org/TR/sparql11-query/#sparqlQueryVariables).
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum NamedNodeOrVariable { pub enum NamedNodePattern {
NamedNode(NamedNode), NamedNode(NamedNode),
Variable(Variable), Variable(Variable),
} }
impl fmt::Display for NamedNodeOrVariable { impl fmt::Display for NamedNodePattern {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
NamedNodeOrVariable::NamedNode(node) => node.fmt(f), NamedNodePattern::NamedNode(node) => node.fmt(f),
NamedNodeOrVariable::Variable(var) => var.fmt(f), NamedNodePattern::Variable(var) => var.fmt(f),
} }
} }
} }
impl From<NamedNode> for NamedNodeOrVariable { impl From<NamedNode> for NamedNodePattern {
#[inline]
fn from(node: NamedNode) -> Self { fn from(node: NamedNode) -> Self {
Self::NamedNode(node) Self::NamedNode(node)
} }
} }
impl From<Variable> for NamedNodeOrVariable { impl From<Variable> for NamedNodePattern {
#[inline]
fn from(var: Variable) -> Self { fn from(var: Variable) -> Self {
Self::Variable(var) Self::Variable(var)
} }
@ -398,152 +402,168 @@ impl From<Variable> for NamedNodeOrVariable {
/// The union of [terms](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-term) and [variables](https://www.w3.org/TR/sparql11-query/#sparqlQueryVariables). /// The union of [terms](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-term) and [variables](https://www.w3.org/TR/sparql11-query/#sparqlQueryVariables).
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum GroundTermOrVariable { pub enum TermPattern {
NamedNode(NamedNode), NamedNode(NamedNode),
BlankNode(BlankNode),
Literal(Literal), Literal(Literal),
Variable(Variable), Variable(Variable),
} }
impl fmt::Display for GroundTermOrVariable { impl fmt::Display for TermPattern {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
GroundTermOrVariable::NamedNode(term) => term.fmt(f), TermPattern::NamedNode(term) => term.fmt(f),
GroundTermOrVariable::Literal(term) => term.fmt(f), TermPattern::BlankNode(term) => term.fmt(f),
GroundTermOrVariable::Variable(var) => var.fmt(f), TermPattern::Literal(term) => term.fmt(f),
TermPattern::Variable(var) => var.fmt(f),
} }
} }
} }
impl From<NamedNode> for GroundTermOrVariable { impl From<NamedNode> for TermPattern {
#[inline]
fn from(node: NamedNode) -> Self { fn from(node: NamedNode) -> Self {
Self::NamedNode(node) Self::NamedNode(node)
} }
} }
impl From<Literal> for GroundTermOrVariable { impl From<BlankNode> for TermPattern {
#[inline]
fn from(node: BlankNode) -> Self {
Self::BlankNode(node)
}
}
impl From<Literal> for TermPattern {
#[inline]
fn from(literal: Literal) -> Self { fn from(literal: Literal) -> Self {
Self::Literal(literal) Self::Literal(literal)
} }
} }
impl From<Variable> for GroundTermOrVariable { impl From<Variable> for TermPattern {
fn from(var: Variable) -> Self { fn from(var: Variable) -> Self {
Self::Variable(var) Self::Variable(var)
} }
} }
impl From<GroundTerm> for GroundTermOrVariable { impl From<Term> for TermPattern {
fn from(term: GroundTerm) -> Self { #[inline]
fn from(term: Term) -> Self {
match term { match term {
GroundTerm::NamedNode(node) => Self::NamedNode(node), Term::NamedNode(node) => Self::NamedNode(node),
GroundTerm::Literal(literal) => Self::Literal(literal), Term::BlankNode(node) => Self::BlankNode(node),
Term::Literal(literal) => Self::Literal(literal),
} }
} }
} }
impl From<NamedNodeOrVariable> for GroundTermOrVariable { impl From<NamedNodePattern> for TermPattern {
fn from(element: NamedNodeOrVariable) -> Self { #[inline]
fn from(element: NamedNodePattern) -> Self {
match element { match element {
NamedNodeOrVariable::NamedNode(node) => Self::NamedNode(node), NamedNodePattern::NamedNode(node) => Self::NamedNode(node),
NamedNodeOrVariable::Variable(var) => Self::Variable(var), NamedNodePattern::Variable(var) => Self::Variable(var),
} }
} }
} }
/// The union of [terms](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-term) and [variables](https://www.w3.org/TR/sparql11-query/#sparqlQueryVariables). /// The union of [terms](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-term) and [variables](https://www.w3.org/TR/sparql11-query/#sparqlQueryVariables) without blank nodes.
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum TermOrVariable { pub enum GroundTermPattern {
NamedNode(NamedNode), NamedNode(NamedNode),
BlankNode(BlankNode),
Literal(Literal), Literal(Literal),
Variable(Variable), Variable(Variable),
} }
impl fmt::Display for TermOrVariable { impl fmt::Display for GroundTermPattern {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
TermOrVariable::NamedNode(term) => term.fmt(f), GroundTermPattern::NamedNode(term) => term.fmt(f),
TermOrVariable::BlankNode(term) => term.fmt(f), GroundTermPattern::Literal(term) => term.fmt(f),
TermOrVariable::Literal(term) => term.fmt(f), GroundTermPattern::Variable(var) => var.fmt(f),
TermOrVariable::Variable(var) => var.fmt(f),
} }
} }
} }
impl From<NamedNode> for TermOrVariable { impl From<NamedNode> for GroundTermPattern {
#[inline]
fn from(node: NamedNode) -> Self { fn from(node: NamedNode) -> Self {
Self::NamedNode(node) Self::NamedNode(node)
} }
} }
impl From<BlankNode> for TermOrVariable { impl From<Literal> for GroundTermPattern {
fn from(node: BlankNode) -> Self { #[inline]
Self::BlankNode(node)
}
}
impl From<Literal> for TermOrVariable {
fn from(literal: Literal) -> Self { fn from(literal: Literal) -> Self {
Self::Literal(literal) Self::Literal(literal)
} }
} }
impl From<Variable> for TermOrVariable { impl From<Variable> for GroundTermPattern {
#[inline]
fn from(var: Variable) -> Self { fn from(var: Variable) -> Self {
Self::Variable(var) Self::Variable(var)
} }
} }
impl From<Term> for TermOrVariable { impl From<GroundTerm> for GroundTermPattern {
fn from(term: Term) -> Self { #[inline]
fn from(term: GroundTerm) -> Self {
match term { match term {
Term::NamedNode(node) => Self::NamedNode(node), GroundTerm::NamedNode(node) => Self::NamedNode(node),
Term::BlankNode(node) => Self::BlankNode(node), GroundTerm::Literal(literal) => Self::Literal(literal),
Term::Literal(literal) => Self::Literal(literal),
} }
} }
} }
impl From<NamedNodeOrVariable> for TermOrVariable { impl From<NamedNodePattern> for GroundTermPattern {
fn from(element: NamedNodeOrVariable) -> Self { #[inline]
fn from(element: NamedNodePattern) -> Self {
match element { match element {
NamedNodeOrVariable::NamedNode(node) => Self::NamedNode(node), NamedNodePattern::NamedNode(node) => Self::NamedNode(node),
NamedNodeOrVariable::Variable(var) => Self::Variable(var), NamedNodePattern::Variable(var) => Self::Variable(var),
} }
} }
} }
/// The union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri), [default graph name](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph) and [variables](https://www.w3.org/TR/sparql11-query/#sparqlQueryVariables). /// The union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri), [default graph name](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph) and [variables](https://www.w3.org/TR/sparql11-query/#sparqlQueryVariables).
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum GraphNameOrVariable { pub enum GraphNamePattern {
NamedNode(NamedNode), NamedNode(NamedNode),
DefaultGraph, DefaultGraph,
Variable(Variable), Variable(Variable),
} }
impl fmt::Display for GraphNameOrVariable { impl fmt::Display for GraphNamePattern {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
GraphNameOrVariable::NamedNode(node) => node.fmt(f), GraphNamePattern::NamedNode(node) => node.fmt(f),
GraphNameOrVariable::DefaultGraph => f.write_str("DEFAULT"), GraphNamePattern::DefaultGraph => f.write_str("DEFAULT"),
GraphNameOrVariable::Variable(var) => var.fmt(f), GraphNamePattern::Variable(var) => var.fmt(f),
} }
} }
} }
impl From<NamedNode> for GraphNameOrVariable { impl From<NamedNode> for GraphNamePattern {
#[inline]
fn from(node: NamedNode) -> Self { fn from(node: NamedNode) -> Self {
Self::NamedNode(node) Self::NamedNode(node)
} }
} }
impl From<Variable> for GraphNameOrVariable { impl From<Variable> for GraphNamePattern {
#[inline]
fn from(var: Variable) -> Self { fn from(var: Variable) -> Self {
Self::Variable(var) Self::Variable(var)
} }
} }
impl From<GraphName> for GraphNameOrVariable { impl From<GraphName> for GraphNamePattern {
#[inline]
fn from(graph_name: GraphName) -> Self { fn from(graph_name: GraphName) -> Self {
match graph_name { match graph_name {
GraphName::NamedNode(node) => Self::NamedNode(node), GraphName::NamedNode(node) => Self::NamedNode(node),
@ -552,11 +572,117 @@ impl From<GraphName> for GraphNameOrVariable {
} }
} }
impl From<NamedNodeOrVariable> for GraphNameOrVariable { impl From<NamedNodePattern> for GraphNamePattern {
fn from(graph_name: NamedNodeOrVariable) -> Self { #[inline]
fn from(graph_name: NamedNodePattern) -> Self {
match graph_name { match graph_name {
NamedNodeOrVariable::NamedNode(node) => Self::NamedNode(node), NamedNodePattern::NamedNode(node) => Self::NamedNode(node),
NamedNodeOrVariable::Variable(var) => Self::Variable(var), NamedNodePattern::Variable(var) => Self::Variable(var),
}
}
}
/// A [triple pattern](https://www.w3.org/TR/sparql11-query/#defn_TriplePattern)
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct TriplePattern {
pub subject: TermPattern,
pub predicate: NamedNodePattern,
pub object: TermPattern,
}
impl TriplePattern {
pub(crate) fn new(
subject: impl Into<TermPattern>,
predicate: impl Into<NamedNodePattern>,
object: impl Into<TermPattern>,
) -> Self {
Self {
subject: subject.into(),
predicate: predicate.into(),
object: object.into(),
}
}
}
impl fmt::Display for TriplePattern {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"(triple {} {} {})",
self.subject, self.predicate, self.object
)
}
}
/// A [triple pattern](https://www.w3.org/TR/sparql11-query/#defn_TriplePattern) in a specific graph
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct QuadPattern {
pub subject: TermPattern,
pub predicate: NamedNodePattern,
pub object: TermPattern,
pub graph_name: GraphNamePattern,
}
impl QuadPattern {
pub(crate) fn new(
subject: impl Into<TermPattern>,
predicate: impl Into<NamedNodePattern>,
object: impl Into<TermPattern>,
graph_name: impl Into<GraphNamePattern>,
) -> Self {
Self {
subject: subject.into(),
predicate: predicate.into(),
object: object.into(),
graph_name: graph_name.into(),
}
}
}
impl fmt::Display for QuadPattern {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.graph_name == GraphNamePattern::DefaultGraph {
write!(
f,
"(triple {} {} {})",
self.subject, self.predicate, self.object
)
} else {
write!(
f,
"(graph {} (triple {} {} {}))",
self.graph_name, self.subject, self.predicate, self.object
)
}
}
}
/// A [triple pattern](https://www.w3.org/TR/sparql11-query/#defn_TriplePattern) in a specific graph without blank nodes
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct GroundQuadPattern {
pub subject: GroundTermPattern,
pub predicate: NamedNodePattern,
pub object: GroundTermPattern,
pub graph_name: GraphNamePattern,
}
impl fmt::Display for GroundQuadPattern {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.graph_name == GraphNamePattern::DefaultGraph {
write!(
f,
"(triple {} {} {})",
self.subject, self.predicate, self.object
)
} else {
write!(
f,
"(graph {} (triple {} {} {}))",
self.graph_name, self.subject, self.predicate, self.object
)
} }
} }
} }

Loading…
Cancel
Save