From bc27a298fa567940e456f5f0acbbcd0e0ace7e17 Mon Sep 17 00:00:00 2001 From: Tpt Date: Sun, 25 Apr 2021 08:14:51 +0200 Subject: [PATCH] Simplifies spargebra basic patterns naming --- lib/src/sparql/plan_builder.rs | 54 +++-- lib/src/sparql/update.rs | 62 +++--- spargebra/src/algebra.rs | 126 ++---------- spargebra/src/parser.rs | 171 ++++++++-------- spargebra/src/query.rs | 1 + spargebra/src/term.rs | 358 ++++++++++++++++++++++----------- 6 files changed, 392 insertions(+), 380 deletions(-) diff --git a/lib/src/sparql/plan_builder.rs b/lib/src/sparql/plan_builder.rs index 1825aa01..f719f29a 100644 --- a/lib/src/sparql/plan_builder.rs +++ b/lib/src/sparql/plan_builder.rs @@ -768,15 +768,15 @@ impl<'a> PlanBuilder<'a> { fn pattern_value_from_term_or_variable( &mut self, - term_or_variable: &TermOrVariable, + term_or_variable: &TermPattern, variables: &mut Vec, ) -> Result { Ok(match term_or_variable { - TermOrVariable::Variable(variable) => { + TermPattern::Variable(variable) => { PatternValue::Variable(variable_key(variables, variable)) } - TermOrVariable::NamedNode(node) => PatternValue::Constant(self.build_named_node(node)?), - TermOrVariable::BlankNode(bnode) => { + TermPattern::NamedNode(node) => PatternValue::Constant(self.build_named_node(node)?), + TermPattern::BlankNode(bnode) => { PatternValue::Variable(variable_key( variables, &Variable { @@ -785,22 +785,20 @@ impl<'a> PlanBuilder<'a> { )) //TODO: very bad hack to convert bnode to variable } - TermOrVariable::Literal(literal) => { - PatternValue::Constant(self.build_literal(literal)?) - } + TermPattern::Literal(literal) => PatternValue::Constant(self.build_literal(literal)?), }) } fn pattern_value_from_named_node_or_variable( &mut self, - named_node_or_variable: &NamedNodeOrVariable, + named_node_or_variable: &NamedNodePattern, variables: &mut Vec, ) -> Result { Ok(match named_node_or_variable { - NamedNodeOrVariable::NamedNode(named_node) => { + NamedNodePattern::NamedNode(named_node) => { PatternValue::Constant(self.build_named_node(named_node)?) } - NamedNodeOrVariable::Variable(variable) => { + NamedNodePattern::Variable(variable) => { PatternValue::Variable(variable_key(variables, variable)) } }) @@ -921,21 +919,21 @@ impl<'a> PlanBuilder<'a> { fn template_value_from_term_or_variable( &mut self, - term_or_variable: &TermOrVariable, + term_or_variable: &TermPattern, variables: &mut Vec, bnodes: &mut Vec, ) -> Result { Ok(match term_or_variable { - TermOrVariable::Variable(variable) => { + TermPattern::Variable(variable) => { TripleTemplateValue::Variable(variable_key(variables, variable)) } - TermOrVariable::NamedNode(node) => { + TermPattern::NamedNode(node) => { TripleTemplateValue::Constant(self.build_named_node(node)?) } - TermOrVariable::BlankNode(bnode) => { + TermPattern::BlankNode(bnode) => { TripleTemplateValue::BlankNode(bnode_key(bnodes, bnode)) } - TermOrVariable::Literal(literal) => { + TermPattern::Literal(literal) => { TripleTemplateValue::Constant(self.build_literal(literal)?) } }) @@ -943,14 +941,14 @@ impl<'a> PlanBuilder<'a> { fn template_value_from_named_node_or_variable( &mut self, - named_node_or_variable: &NamedNodeOrVariable, + named_node_or_variable: &NamedNodePattern, variables: &mut Vec, ) -> Result { Ok(match named_node_or_variable { - NamedNodeOrVariable::Variable(variable) => { + NamedNodePattern::Variable(variable) => { TripleTemplateValue::Variable(variable_key(variables, variable)) } - NamedNodeOrVariable::NamedNode(term) => { + NamedNodePattern::NamedNode(term) => { TripleTemplateValue::Constant(self.build_named_node(term)?) } }) @@ -1126,29 +1124,29 @@ fn count_pattern_binds( assigned_blank_nodes: &HashSet<&BlankNode>, ) -> u8 { let mut count = 12; - if let TermOrVariable::Variable(v) = &pattern.subject { + if let TermPattern::Variable(v) = &pattern.subject { if !assigned_variables.contains(v) { count -= 4; } - } else if let TermOrVariable::BlankNode(bnode) = &pattern.subject { + } else if let TermPattern::BlankNode(bnode) = &pattern.subject { if !assigned_blank_nodes.contains(bnode) { count -= 4; } } else { count -= 1; } - if let NamedNodeOrVariable::Variable(v) = &pattern.predicate { + if let NamedNodePattern::Variable(v) = &pattern.predicate { if !assigned_variables.contains(v) { count -= 4; } } else { count -= 1; } - if let TermOrVariable::Variable(v) = &pattern.object { + if let TermPattern::Variable(v) = &pattern.object { if !assigned_variables.contains(v) { count -= 4; } - } else if let TermOrVariable::BlankNode(bnode) = &pattern.object { + } else if let TermPattern::BlankNode(bnode) = &pattern.object { if !assigned_blank_nodes.contains(bnode) { count -= 4; } @@ -1163,17 +1161,17 @@ fn add_pattern_variables<'a>( variables: &mut HashSet<&'a Variable>, blank_nodes: &mut HashSet<&'a BlankNode>, ) { - if let TermOrVariable::Variable(v) = &pattern.subject { + if let TermPattern::Variable(v) = &pattern.subject { variables.insert(v); - } else if let TermOrVariable::BlankNode(bnode) = &pattern.subject { + } else if let TermPattern::BlankNode(bnode) = &pattern.subject { blank_nodes.insert(bnode); } - if let NamedNodeOrVariable::Variable(v) = &pattern.predicate { + if let NamedNodePattern::Variable(v) = &pattern.predicate { variables.insert(v); } - if let TermOrVariable::Variable(v) = &pattern.object { + if let TermPattern::Variable(v) = &pattern.object { variables.insert(v); - } else if let TermOrVariable::BlankNode(bnode) = &pattern.object { + } else if let TermPattern::BlankNode(bnode) = &pattern.object { blank_nodes.insert(bnode); } } diff --git a/lib/src/sparql/update.rs b/lib/src/sparql/update.rs index 4a5d8dca..82222ea8 100644 --- a/lib/src/sparql/update.rs +++ b/lib/src/sparql/update.rs @@ -16,11 +16,11 @@ use crate::storage::Storage; use http::header::{ACCEPT, CONTENT_TYPE, USER_AGENT}; use http::{Method, Request, StatusCode}; use oxiri::Iri; -use spargebra::algebra::{GraphPattern, GraphTarget, GroundQuadPattern, QuadPattern}; +use spargebra::algebra::{GraphPattern, GraphTarget}; use spargebra::term::{ - BlankNode, GraphName, GraphNameOrVariable, GroundQuad, GroundTerm, GroundTermOrVariable, - Literal, NamedNode, NamedNodeOrVariable, NamedOrBlankNode, Quad, Term, TermOrVariable, - Variable, + BlankNode, GraphName, GraphNamePattern, GroundQuad, GroundQuadPattern, GroundTerm, + GroundTermPattern, Literal, NamedNode, NamedNodePattern, NamedOrBlankNode, Quad, QuadPattern, + Term, TermPattern, Variable, }; use spargebra::GraphUpdateOperation; use std::collections::HashMap; @@ -376,36 +376,32 @@ impl<'a> SimpleUpdateEvaluator<'a> { fn encode_term_or_var_for_insertion( &mut self, - term: &TermOrVariable, + term: &TermPattern, variables: &[Variable], values: &[Option], bnodes: &mut HashMap, validate: impl FnOnce(&EncodedTerm) -> bool, ) -> Result, EvaluationError> { Ok(match term { - TermOrVariable::NamedNode(term) => Some(self.encode_named_node_for_insertion(term)?), - TermOrVariable::BlankNode(bnode) => Some( + TermPattern::NamedNode(term) => Some(self.encode_named_node_for_insertion(term)?), + TermPattern::BlankNode(bnode) => Some( self.storage .encode_blank_node(bnodes.entry(bnode.clone()).or_default().as_ref())?, ), - TermOrVariable::Literal(term) => Some(self.encode_literal_for_insertion(term)?), - TermOrVariable::Variable(v) => { - self.lookup_variable(v, variables, values).filter(validate) - } + TermPattern::Literal(term) => Some(self.encode_literal_for_insertion(term)?), + TermPattern::Variable(v) => self.lookup_variable(v, variables, values).filter(validate), }) } fn encode_named_node_or_var_for_insertion( &mut self, - term: &NamedNodeOrVariable, + term: &NamedNodePattern, variables: &[Variable], values: &[Option], ) -> Result, EvaluationError> { Ok(match term { - NamedNodeOrVariable::NamedNode(term) => { - Some(self.encode_named_node_for_insertion(term)?) - } - NamedNodeOrVariable::Variable(v) => self + NamedNodePattern::NamedNode(term) => Some(self.encode_named_node_for_insertion(term)?), + NamedNodePattern::Variable(v) => self .lookup_variable(v, variables, values) .filter(|value| value.is_named_node()), }) @@ -413,16 +409,14 @@ impl<'a> SimpleUpdateEvaluator<'a> { fn encode_graph_name_or_var_for_insertion( &mut self, - term: &GraphNameOrVariable, + term: &GraphNamePattern, variables: &[Variable], values: &[Option], ) -> Result, EvaluationError> { Ok(match term { - GraphNameOrVariable::NamedNode(term) => { - Some(self.encode_named_node_for_insertion(term)?) - } - GraphNameOrVariable::DefaultGraph => Some(EncodedTerm::DefaultGraph), - GraphNameOrVariable::Variable(v) => self + GraphNamePattern::NamedNode(term) => Some(self.encode_named_node_for_insertion(term)?), + GraphNamePattern::DefaultGraph => Some(EncodedTerm::DefaultGraph), + GraphNamePattern::Variable(v) => self .lookup_variable(v, variables, values) .filter(|value| value.is_named_node()), }) @@ -510,28 +504,26 @@ impl<'a> SimpleUpdateEvaluator<'a> { fn encode_term_or_var_for_deletion( &self, - term: &GroundTermOrVariable, + term: &GroundTermPattern, variables: &[Variable], values: &[Option], ) -> Option { match term { - GroundTermOrVariable::NamedNode(term) => { - Some(self.encode_named_node_for_deletion(term)) - } - GroundTermOrVariable::Literal(term) => Some(self.encode_literal_for_deletion(term)), - GroundTermOrVariable::Variable(v) => self.lookup_variable(v, variables, values), + GroundTermPattern::NamedNode(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), } } fn encode_named_node_or_var_for_deletion( &self, - term: &NamedNodeOrVariable, + term: &NamedNodePattern, variables: &[Variable], values: &[Option], ) -> Option { match term { - NamedNodeOrVariable::NamedNode(term) => Some(self.encode_named_node_for_deletion(term)), - NamedNodeOrVariable::Variable(v) => self + NamedNodePattern::NamedNode(term) => Some(self.encode_named_node_for_deletion(term)), + NamedNodePattern::Variable(v) => self .lookup_variable(v, variables, values) .filter(|v| v.is_named_node()), } @@ -539,14 +531,14 @@ impl<'a> SimpleUpdateEvaluator<'a> { fn encode_graph_name_or_var_for_deletion( &self, - graph_name: &GraphNameOrVariable, + graph_name: &GraphNamePattern, variables: &[Variable], values: &[Option], ) -> Option { match graph_name { - GraphNameOrVariable::NamedNode(term) => Some(self.encode_named_node_for_deletion(term)), - GraphNameOrVariable::DefaultGraph => Some(EncodedTerm::DefaultGraph), - GraphNameOrVariable::Variable(v) => self + GraphNamePattern::NamedNode(term) => Some(self.encode_named_node_for_deletion(term)), + GraphNamePattern::DefaultGraph => Some(EncodedTerm::DefaultGraph), + GraphNamePattern::Variable(v) => self .lookup_variable(v, variables, values) .filter(|v| v.is_named_node()), } diff --git a/spargebra/src/algebra.rs b/spargebra/src/algebra.rs index 55b59209..746e6709 100644 --- a/spargebra/src/algebra.rs +++ b/spargebra/src/algebra.rs @@ -5,38 +5,6 @@ use crate::term::*; use std::collections::BTreeSet; 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, - predicate: impl Into, - object: impl Into, - ) -> 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); 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, - predicate: impl Into, - object: impl Into, - graph_name: impl Into, - ) -> 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); impl<'a> fmt::Display for SparqlQuadPattern<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.0.graph_name == GraphNameOrVariable::DefaultGraph { + if self.0.graph_name == GraphNamePattern::DefaultGraph { write!( f, "{} {} {} .", @@ -143,7 +41,7 @@ pub(crate) struct SparqlGroundQuadPattern<'a>(pub(crate) &'a GroundQuadPattern); impl<'a> fmt::Display for SparqlGroundQuadPattern<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.0.graph_name == GraphNameOrVariable::DefaultGraph { + if self.0.graph_name == GraphNamePattern::DefaultGraph { write!( f, "{} {} {} .", @@ -570,9 +468,9 @@ pub enum GraphPattern { Bgp(Vec), /// A [property path pattern](https://www.w3.org/TR/sparql11-query/#defn_evalPP_predicate) Path { - subject: TermOrVariable, + subject: TermPattern, path: PropertyPathExpression, - object: TermOrVariable, + object: TermPattern, }, /// [Join](https://www.w3.org/TR/sparql11-query/#defn_algJoin) Join { @@ -596,7 +494,7 @@ pub enum GraphPattern { right: Box, }, Graph { - graph_name: NamedNodeOrVariable, + graph_name: NamedNodePattern, inner: Box, }, /// [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 { - name: NamedNodeOrVariable, + name: NamedNodePattern, pattern: Box, silent: bool, }, @@ -783,13 +681,13 @@ impl GraphPattern { match self { GraphPattern::Bgp(p) => { for pattern in p { - if let TermOrVariable::Variable(s) = &pattern.subject { + if let TermPattern::Variable(s) = &pattern.subject { vars.insert(s); } - if let NamedNodeOrVariable::Variable(p) = &pattern.predicate { + if let NamedNodePattern::Variable(p) = &pattern.predicate { vars.insert(p); } - if let TermOrVariable::Variable(o) = &pattern.object { + if let TermPattern::Variable(o) = &pattern.object { vars.insert(o); } } @@ -797,10 +695,10 @@ impl GraphPattern { GraphPattern::Path { subject, object, .. } => { - if let TermOrVariable::Variable(s) = subject { + if let TermPattern::Variable(s) = subject { vars.insert(s); } - if let TermOrVariable::Variable(o) = object { + if let TermPattern::Variable(o) = object { vars.insert(o); } } @@ -812,7 +710,7 @@ impl GraphPattern { } GraphPattern::Filter { inner, .. } => inner.add_visible_variables(vars), GraphPattern::Graph { graph_name, inner } => { - if let NamedNodeOrVariable::Variable(ref g) = graph_name { + if let NamedNodePattern::Variable(ref g) = graph_name { vars.insert(g); } inner.add_visible_variables(vars); diff --git a/spargebra/src/parser.rs b/spargebra/src/parser.rs index 884e0f3b..83e944a9 100644 --- a/spargebra/src/parser.rs +++ b/spargebra/src/parser.rs @@ -139,9 +139,9 @@ impl From for VariableOrPropertyPath { } fn add_to_triple_or_path_patterns( - subject: TermOrVariable, + subject: TermPattern, predicate: impl Into, - object: TermOrVariable, + object: TermPattern, patterns: &mut Vec, ) { match predicate.into() { @@ -199,9 +199,9 @@ fn build_bgp(patterns: Vec) -> GraphPattern { enum TripleOrPathPattern { Triple(TriplePattern), Path { - subject: TermOrVariable, + subject: TermPattern, path: PropertyPathExpression, - object: TermOrVariable, + object: TermPattern, }, } @@ -454,10 +454,7 @@ fn build_select( m } -fn copy_graph( - from: impl Into, - to: impl Into, -) -> GraphUpdateOperation { +fn copy_graph(from: impl Into, to: impl Into) -> GraphUpdateOperation { let bgp = GraphPattern::Bgp(vec![TriplePattern::new( Variable { name: "s".into() }, Variable { name: "p".into() }, @@ -840,14 +837,14 @@ parser! { pattern: build_select(Selection { option: SelectionOption::Default, variables: Some(p.into_iter().map(|var_or_iri| match var_or_iri { - NamedNodeOrVariable::NamedNode(n) => SelectionMember::Expression(n.into(), variable()), - NamedNodeOrVariable::Variable(v) => SelectionMember::Variable(v) + NamedNodePattern::NamedNode(n) => SelectionMember::Expression(n.into(), variable()), + NamedNodePattern::Variable(v) => SelectionMember::Variable(v) }).collect()) }, w.unwrap_or_else(GraphPattern::default), g, h, o, l, v, state), base_iri: state.base_iri.clone() } } - rule DescribeQuery_item() -> NamedNodeOrVariable = i:VarOrIri() _ { i } + rule DescribeQuery_item() -> NamedNodePattern = i:VarOrIri() _ { i } //[12] 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 bgp = GraphPattern::Bgp(vec![TriplePattern::new(q.subject.clone(), q.predicate.clone(), q.object.clone())]); match &q.graph_name { - GraphNameOrVariable::NamedNode(graph_name) => GraphPattern::Graph { graph_name: graph_name.clone().into(), inner: Box::new(bgp) }, - GraphNameOrVariable::DefaultGraph => bgp, - GraphNameOrVariable::Variable(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) }, + GraphNamePattern::DefaultGraph => bgp, + GraphNamePattern::Variable(graph_name) => GraphPattern::Graph { graph_name: graph_name.clone().into(), inner: Box::new(bgp) }, } }).fold(GraphPattern::Bgp(Vec::new()), new_join); let delete = d.into_iter().map(|q| Ok(GroundQuadPattern { subject: match q.subject { - TermOrVariable::NamedNode(subject) => subject.into(), - TermOrVariable::BlankNode(_) => return Err("Blank nodes are not allowed in DELETE WHERE"), - TermOrVariable::Literal(subject) => subject.into(), - TermOrVariable::Variable(subject) => subject.into(), + TermPattern::NamedNode(subject) => subject.into(), + TermPattern::BlankNode(_) => return Err("Blank nodes are not allowed in DELETE WHERE"), + TermPattern::Literal(subject) => subject.into(), + TermPattern::Variable(subject) => subject.into(), }, predicate: q.predicate, object: match q.object { - TermOrVariable::NamedNode(object) => object.into(), - TermOrVariable::BlankNode(_) => return Err("Blank nodes are not allowed in DELETE WHERE"), - TermOrVariable::Literal(object) => object.into(), - TermOrVariable::Variable(object) => object.into(), + TermPattern::NamedNode(object) => object.into(), + TermPattern::BlankNode(_) => return Err("Blank nodes are not allowed in DELETE WHERE"), + TermPattern::Literal(object) => object.into(), + TermPattern::Variable(object) => object.into(), }, graph_name: q.graph_name })).collect::,_>>()?; @@ -1091,7 +1088,7 @@ parser! { if let Some(with) = with { // 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 { subject: q.subject, predicate: q.predicate, @@ -1101,7 +1098,7 @@ parser! { } else { q }).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 { subject: q.subject, predicate: q.predicate, @@ -1138,17 +1135,17 @@ parser! { rule DeleteClause() -> Vec = i("DELETE") _ q:QuadPattern() {? q.into_iter().map(|q| Ok(GroundQuadPattern { subject: match q.subject { - TermOrVariable::NamedNode(subject) => subject.into(), - TermOrVariable::BlankNode(_) => return Err("Blank nodes are not allowed in DELETE WHERE"), - TermOrVariable::Literal(subject) => subject.into(), - TermOrVariable::Variable(subject) => subject.into(), + TermPattern::NamedNode(subject) => subject.into(), + TermPattern::BlankNode(_) => return Err("Blank nodes are not allowed in DELETE WHERE"), + TermPattern::Literal(subject) => subject.into(), + TermPattern::Variable(subject) => subject.into(), }, predicate: q.predicate, object: match q.object { - TermOrVariable::NamedNode(object) => object.into(), - TermOrVariable::BlankNode(_) => return Err("Blank nodes are not allowed in DELETE WHERE"), - TermOrVariable::Literal(object) => object.into(), - TermOrVariable::Variable(object) => object.into(), + TermPattern::NamedNode(object) => object.into(), + TermPattern::BlankNode(_) => return Err("Blank nodes are not allowed in DELETE WHERE"), + TermPattern::Literal(object) => object.into(), + TermPattern::Variable(object) => object.into(), }, graph_name: q.graph_name })).collect::,_>>() @@ -1189,49 +1186,49 @@ parser! { rule QuadData() -> Vec = "{" _ q:Quads() _ "}" {? q.into_iter().map(|q| Ok(Quad { subject: match q.subject { - TermOrVariable::NamedNode(t) => t.into(), - TermOrVariable::BlankNode(t) => t.into(), - TermOrVariable::Literal(_) | TermOrVariable::Variable(_) => return Err(()) + TermPattern::NamedNode(t) => t.into(), + TermPattern::BlankNode(t) => t.into(), + TermPattern::Literal(_) | TermPattern::Variable(_) => return Err(()) }, - predicate: if let NamedNodeOrVariable::NamedNode(t) = q.predicate { + predicate: if let NamedNodePattern::NamedNode(t) = q.predicate { t } else { return Err(()) }, object: match q.object { - TermOrVariable::NamedNode(t) => t.into(), - TermOrVariable::BlankNode(t) => t.into(), - TermOrVariable::Literal(t) => t.into(), - TermOrVariable::Variable(_) => return Err(()) + TermPattern::NamedNode(t) => t.into(), + TermPattern::BlankNode(t) => t.into(), + TermPattern::Literal(t) => t.into(), + TermPattern::Variable(_) => return Err(()) }, graph_name: match q.graph_name { - GraphNameOrVariable::NamedNode(t) => t.into(), - GraphNameOrVariable::DefaultGraph => GraphName::DefaultGraph, - GraphNameOrVariable::Variable(_) => return Err(()) + GraphNamePattern::NamedNode(t) => t.into(), + GraphNamePattern::DefaultGraph => GraphName::DefaultGraph, + GraphNamePattern::Variable(_) => return Err(()) } })).collect::, ()>>().map_err(|_| "Variables are not allowed in INSERT DATA and DELETE DATA") } rule GroundQuadData() -> Vec = "{" _ q:Quads() _ "}" {? q.into_iter().map(|q| Ok(GroundQuad { - subject: if let TermOrVariable::NamedNode(t) = q.subject { + subject: if let TermPattern::NamedNode(t) = q.subject { t } else { return Err(()) }, - predicate: if let NamedNodeOrVariable::NamedNode(t) = q.predicate { + predicate: if let NamedNodePattern::NamedNode(t) = q.predicate { t } else { return Err(()) }, object: match q.object { - TermOrVariable::NamedNode(t) => t.into(), - TermOrVariable::Literal(t) => t.into(), - TermOrVariable::BlankNode(_) | TermOrVariable::Variable(_) => return Err(()) + TermPattern::NamedNode(t) => t.into(), + TermPattern::Literal(t) => t.into(), + TermPattern::BlankNode(_) | TermPattern::Variable(_) => return Err(()) }, graph_name: match q.graph_name { - GraphNameOrVariable::NamedNode(t) => t.into(), - GraphNameOrVariable::DefaultGraph => GraphName::DefaultGraph, - GraphNameOrVariable::Variable(_) => return Err(()) + GraphNamePattern::NamedNode(t) => t.into(), + GraphNamePattern::DefaultGraph => GraphName::DefaultGraph, + GraphNamePattern::Variable(_) => return Err(()) } })).collect::, ()>>().map_err(|_| "Variables are not allowed in INSERT DATA and DELETE DATA") } @@ -1241,7 +1238,7 @@ parser! { q.into_iter().flatten().collect() } rule Quads_TriplesTemplate() -> Vec = 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? rule Quads_QuadsNotTriples() -> Vec = q:QuadsNotTriples() _ "."? { q } @@ -1452,19 +1449,19 @@ parser! { } //[76] - rule PropertyList() -> FocusedTriplePattern)>> = + rule PropertyList() -> FocusedTriplePattern)>> = PropertyListNotEmpty() / { FocusedTriplePattern::default() } //[77] - rule PropertyListNotEmpty() -> FocusedTriplePattern)>> = l:PropertyListNotEmpty_item() **<1,> (";" _) { - l.into_iter().fold(FocusedTriplePattern::)>>::default(), |mut a, b| { + rule PropertyListNotEmpty() -> FocusedTriplePattern)>> = l:PropertyListNotEmpty_item() **<1,> (";" _) { + l.into_iter().fold(FocusedTriplePattern::)>>::default(), |mut a, b| { a.focus.push(b.focus); a.patterns.extend(b.patterns); a }) } - rule PropertyListNotEmpty_item() -> FocusedTriplePattern<(NamedNodeOrVariable,Vec)> = p:Verb() _ o:ObjectList() _ { + rule PropertyListNotEmpty_item() -> FocusedTriplePattern<(NamedNodePattern,Vec)> = p:Verb() _ o:ObjectList() _ { FocusedTriplePattern { focus: (p, o.focus), patterns: o.patterns @@ -1472,20 +1469,20 @@ parser! { } //[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] - rule ObjectList() -> FocusedTriplePattern> = o:ObjectList_item() **<1,> ("," _) { - o.into_iter().fold(FocusedTriplePattern::>::default(), |mut a, b| { + rule ObjectList() -> FocusedTriplePattern> = o:ObjectList_item() **<1,> ("," _) { + o.into_iter().fold(FocusedTriplePattern::>::default(), |mut a, b| { a.focus.push(b.focus); a.patterns.extend_from_slice(&b.patterns); a }) } - rule ObjectList_item() -> FocusedTriplePattern = o:Object() _ { o } + rule ObjectList_item() -> FocusedTriplePattern = o:Object() _ { o } //[80] - rule Object() -> FocusedTriplePattern = GraphNode() + rule Object() -> FocusedTriplePattern = GraphNode() //[81] rule TriplesSameSubjectPath() -> Vec = @@ -1510,12 +1507,12 @@ parser! { } //[82] - rule PropertyListPath() -> FocusedTripleOrPathPattern)>> = + rule PropertyListPath() -> FocusedTripleOrPathPattern)>> = PropertyListPathNotEmpty() / { FocusedTripleOrPathPattern::default() } //[83] - rule PropertyListPathNotEmpty() -> FocusedTripleOrPathPattern)>> = hp:(VerbPath() / VerbSimple()) _ ho:ObjectListPath() _ t:PropertyListPathNotEmpty_item()* { + rule PropertyListPathNotEmpty() -> FocusedTripleOrPathPattern)>> = hp:(VerbPath() / VerbSimple()) _ ho:ObjectListPath() _ t:PropertyListPathNotEmpty_item()* { t.into_iter().flat_map(|e| e.into_iter()).fold(FocusedTripleOrPathPattern { focus: vec![(hp, ho.focus)], patterns: ho.patterns @@ -1525,10 +1522,10 @@ parser! { a }) } - rule PropertyListPathNotEmpty_item() -> Option)>> = ";" _ c:PropertyListPathNotEmpty_item_content()? { + rule PropertyListPathNotEmpty_item() -> Option)>> = ";" _ c:PropertyListPathNotEmpty_item_content()? { c } - rule PropertyListPathNotEmpty_item_content() -> FocusedTriplePattern<(VariableOrPropertyPath,Vec)> = p:(VerbPath() / VerbSimple()) _ o:ObjectList() _ { + rule PropertyListPathNotEmpty_item_content() -> FocusedTriplePattern<(VariableOrPropertyPath,Vec)> = p:(VerbPath() / VerbSimple()) _ o:ObjectList() _ { FocusedTriplePattern { focus: (p, o.focus), patterns: o.patterns @@ -1546,17 +1543,17 @@ parser! { } //[86] - rule ObjectListPath() -> FocusedTripleOrPathPattern> = o:ObjectPath_item() **<1,> ("," _) { - o.into_iter().fold(FocusedTripleOrPathPattern::>::default(), |mut a, b| { + rule ObjectListPath() -> FocusedTripleOrPathPattern> = o:ObjectPath_item() **<1,> ("," _) { + o.into_iter().fold(FocusedTripleOrPathPattern::>::default(), |mut a, b| { a.focus.push(b.focus); a.patterns.extend(b.patterns); a }) } - rule ObjectPath_item() -> FocusedTripleOrPathPattern = o:ObjectPath() _ { o } + rule ObjectPath_item() -> FocusedTripleOrPathPattern = o:ObjectPath() _ { o } //[87] - rule ObjectPath() -> FocusedTripleOrPathPattern = GraphNodePath() + rule ObjectPath() -> FocusedTripleOrPathPattern = GraphNodePath() //[88] rule Path() -> PropertyPathExpression = PathAlternative() @@ -1634,12 +1631,12 @@ parser! { "a" { Either::Left(iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")) } //[98] - rule TriplesNode() -> FocusedTriplePattern = Collection() / BlankNodePropertyList() + rule TriplesNode() -> FocusedTriplePattern = Collection() / BlankNodePropertyList() //[99] - rule BlankNodePropertyList() -> FocusedTriplePattern = "[" _ po:PropertyListNotEmpty() _ "]" { + rule BlankNodePropertyList() -> FocusedTriplePattern = "[" _ po:PropertyListNotEmpty() _ "]" { let mut patterns: Vec = Vec::default(); - let mut bnode = TermOrVariable::from(bnode()); + let mut bnode = TermPattern::from(bnode()); for (p, os) in po.focus { for o in os { patterns.push(TriplePattern::new(bnode.clone(), p.clone(), o)); @@ -1652,12 +1649,12 @@ parser! { } //[100] - rule TriplesNodePath() -> FocusedTripleOrPathPattern = CollectionPath() / BlankNodePropertyListPath() + rule TriplesNodePath() -> FocusedTripleOrPathPattern = CollectionPath() / BlankNodePropertyListPath() //[101] - rule BlankNodePropertyListPath() -> FocusedTripleOrPathPattern = "[" _ po:PropertyListPathNotEmpty() _ "]" { + rule BlankNodePropertyListPath() -> FocusedTripleOrPathPattern = "[" _ po:PropertyListPathNotEmpty() _ "]" { let mut patterns: Vec = Vec::default(); - let mut bnode = TermOrVariable::from(bnode()); + let mut bnode = TermPattern::from(bnode()); for (p, os) in po.focus { for o in os { add_to_triple_or_path_patterns(bnode.clone(), p.clone(), o, &mut patterns); @@ -1670,11 +1667,11 @@ parser! { } //[102] - rule Collection() -> FocusedTriplePattern = "(" _ o:Collection_item()+ ")" { + rule Collection() -> FocusedTriplePattern = "(" _ o:Collection_item()+ ")" { let mut patterns: Vec = 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() { - 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#rest"), current_list_node)); current_list_node = new_blank_node; @@ -1685,14 +1682,14 @@ parser! { patterns } } - rule Collection_item() -> FocusedTriplePattern = o:GraphNode() _ { o } + rule Collection_item() -> FocusedTriplePattern = o:GraphNode() _ { o } //[103] - rule CollectionPath() -> FocusedTripleOrPathPattern = "(" _ o:CollectionPath_item()+ _ ")" { + rule CollectionPath() -> FocusedTripleOrPathPattern = "(" _ o:CollectionPath_item()+ _ ")" { let mut patterns: Vec = 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() { - 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#rest"), current_list_node).into()); current_list_node = new_blank_node; @@ -1703,25 +1700,25 @@ parser! { patterns } } - rule CollectionPath_item() -> FocusedTripleOrPathPattern = p:GraphNodePath() _ { p } + rule CollectionPath_item() -> FocusedTripleOrPathPattern = p:GraphNodePath() _ { p } //[104] - rule GraphNode() -> FocusedTriplePattern = + rule GraphNode() -> FocusedTriplePattern = t:VarOrTerm() { FocusedTriplePattern::new(t) } / TriplesNode() //[105] - rule GraphNodePath() -> FocusedTripleOrPathPattern = + rule GraphNodePath() -> FocusedTripleOrPathPattern = t:VarOrTerm() { FocusedTripleOrPathPattern::new(t) } / TriplesNodePath() //[106] - rule VarOrTerm() -> TermOrVariable = + rule VarOrTerm() -> TermPattern = v:Var() { v.into() } / t:GraphTerm() { t.into() } //[107] - rule VarOrIri() -> NamedNodeOrVariable = + rule VarOrIri() -> NamedNodePattern = v:Var() { v.into() } / i:iri() { i.into() } diff --git a/spargebra/src/query.rs b/spargebra/src/query.rs index 16106adf..1edc177e 100644 --- a/spargebra/src/query.rs +++ b/spargebra/src/query.rs @@ -1,5 +1,6 @@ use crate::algebra::*; use crate::parser::{parse_query, ParseError}; +use crate::term::*; use oxiri::Iri; use std::convert::TryFrom; use std::fmt; diff --git a/spargebra/src/term.rs b/spargebra/src/term.rs index ae5a8216..56b57cfd 100644 --- a/spargebra/src/term.rs +++ b/spargebra/src/term.rs @@ -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 default string formatter is returning an N-Triples, Turtle and SPARQL compatible representation. @@ -174,39 +152,6 @@ impl From 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 for GroundTerm { - #[inline] - fn from(node: NamedNode) -> Self { - Self::NamedNode(node) - } -} - -impl From for GroundTerm { - #[inline] - fn from(literal: Literal) -> Self { - Self::Literal(literal) - } -} - /// 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). @@ -261,8 +206,42 @@ impl From 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 for GroundTerm { + #[inline] + fn from(node: NamedNode) -> Self { + Self::NamedNode(node) + } +} + +impl From for GroundTerm { + #[inline] + fn from(literal: Literal) -> Self { + Self::Literal(literal) + } +} + /// 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)] pub enum GraphName { 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). #[derive(Eq, PartialEq, Debug, Clone, Hash)] -pub enum NamedNodeOrVariable { +pub enum NamedNodePattern { NamedNode(NamedNode), Variable(Variable), } -impl fmt::Display for NamedNodeOrVariable { +impl fmt::Display for NamedNodePattern { + #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - NamedNodeOrVariable::NamedNode(node) => node.fmt(f), - NamedNodeOrVariable::Variable(var) => var.fmt(f), + NamedNodePattern::NamedNode(node) => node.fmt(f), + NamedNodePattern::Variable(var) => var.fmt(f), } } } -impl From for NamedNodeOrVariable { +impl From for NamedNodePattern { + #[inline] fn from(node: NamedNode) -> Self { Self::NamedNode(node) } } -impl From for NamedNodeOrVariable { +impl From for NamedNodePattern { + #[inline] fn from(var: Variable) -> Self { Self::Variable(var) } @@ -398,152 +402,168 @@ impl From 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). #[derive(Eq, PartialEq, Debug, Clone, Hash)] -pub enum GroundTermOrVariable { +pub enum TermPattern { NamedNode(NamedNode), + BlankNode(BlankNode), Literal(Literal), Variable(Variable), } -impl fmt::Display for GroundTermOrVariable { +impl fmt::Display for TermPattern { + #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - GroundTermOrVariable::NamedNode(term) => term.fmt(f), - GroundTermOrVariable::Literal(term) => term.fmt(f), - GroundTermOrVariable::Variable(var) => var.fmt(f), + TermPattern::NamedNode(term) => term.fmt(f), + TermPattern::BlankNode(term) => term.fmt(f), + TermPattern::Literal(term) => term.fmt(f), + TermPattern::Variable(var) => var.fmt(f), } } } -impl From for GroundTermOrVariable { +impl From for TermPattern { + #[inline] fn from(node: NamedNode) -> Self { Self::NamedNode(node) } } -impl From for GroundTermOrVariable { +impl From for TermPattern { + #[inline] + fn from(node: BlankNode) -> Self { + Self::BlankNode(node) + } +} + +impl From for TermPattern { + #[inline] fn from(literal: Literal) -> Self { Self::Literal(literal) } } -impl From for GroundTermOrVariable { +impl From for TermPattern { fn from(var: Variable) -> Self { Self::Variable(var) } } -impl From for GroundTermOrVariable { - fn from(term: GroundTerm) -> Self { +impl From for TermPattern { + #[inline] + fn from(term: Term) -> Self { match term { - GroundTerm::NamedNode(node) => Self::NamedNode(node), - GroundTerm::Literal(literal) => Self::Literal(literal), + Term::NamedNode(node) => Self::NamedNode(node), + Term::BlankNode(node) => Self::BlankNode(node), + Term::Literal(literal) => Self::Literal(literal), } } } -impl From for GroundTermOrVariable { - fn from(element: NamedNodeOrVariable) -> Self { +impl From for TermPattern { + #[inline] + fn from(element: NamedNodePattern) -> Self { match element { - NamedNodeOrVariable::NamedNode(node) => Self::NamedNode(node), - NamedNodeOrVariable::Variable(var) => Self::Variable(var), + NamedNodePattern::NamedNode(node) => Self::NamedNode(node), + 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)] -pub enum TermOrVariable { +pub enum GroundTermPattern { NamedNode(NamedNode), - BlankNode(BlankNode), Literal(Literal), Variable(Variable), } -impl fmt::Display for TermOrVariable { +impl fmt::Display for GroundTermPattern { + #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - TermOrVariable::NamedNode(term) => term.fmt(f), - TermOrVariable::BlankNode(term) => term.fmt(f), - TermOrVariable::Literal(term) => term.fmt(f), - TermOrVariable::Variable(var) => var.fmt(f), + GroundTermPattern::NamedNode(term) => term.fmt(f), + GroundTermPattern::Literal(term) => term.fmt(f), + GroundTermPattern::Variable(var) => var.fmt(f), } } } -impl From for TermOrVariable { +impl From for GroundTermPattern { + #[inline] fn from(node: NamedNode) -> Self { Self::NamedNode(node) } } -impl From for TermOrVariable { - fn from(node: BlankNode) -> Self { - Self::BlankNode(node) - } -} - -impl From for TermOrVariable { +impl From for GroundTermPattern { + #[inline] fn from(literal: Literal) -> Self { Self::Literal(literal) } } -impl From for TermOrVariable { +impl From for GroundTermPattern { + #[inline] fn from(var: Variable) -> Self { Self::Variable(var) } } -impl From for TermOrVariable { - fn from(term: Term) -> Self { +impl From for GroundTermPattern { + #[inline] + fn from(term: GroundTerm) -> Self { match term { - Term::NamedNode(node) => Self::NamedNode(node), - Term::BlankNode(node) => Self::BlankNode(node), - Term::Literal(literal) => Self::Literal(literal), + GroundTerm::NamedNode(node) => Self::NamedNode(node), + GroundTerm::Literal(literal) => Self::Literal(literal), } } } -impl From for TermOrVariable { - fn from(element: NamedNodeOrVariable) -> Self { +impl From for GroundTermPattern { + #[inline] + fn from(element: NamedNodePattern) -> Self { match element { - NamedNodeOrVariable::NamedNode(node) => Self::NamedNode(node), - NamedNodeOrVariable::Variable(var) => Self::Variable(var), + NamedNodePattern::NamedNode(node) => Self::NamedNode(node), + 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). #[derive(Eq, PartialEq, Debug, Clone, Hash)] -pub enum GraphNameOrVariable { +pub enum GraphNamePattern { NamedNode(NamedNode), DefaultGraph, Variable(Variable), } -impl fmt::Display for GraphNameOrVariable { +impl fmt::Display for GraphNamePattern { + #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - GraphNameOrVariable::NamedNode(node) => node.fmt(f), - GraphNameOrVariable::DefaultGraph => f.write_str("DEFAULT"), - GraphNameOrVariable::Variable(var) => var.fmt(f), + GraphNamePattern::NamedNode(node) => node.fmt(f), + GraphNamePattern::DefaultGraph => f.write_str("DEFAULT"), + GraphNamePattern::Variable(var) => var.fmt(f), } } } -impl From for GraphNameOrVariable { +impl From for GraphNamePattern { + #[inline] fn from(node: NamedNode) -> Self { Self::NamedNode(node) } } -impl From for GraphNameOrVariable { +impl From for GraphNamePattern { + #[inline] fn from(var: Variable) -> Self { Self::Variable(var) } } -impl From for GraphNameOrVariable { +impl From for GraphNamePattern { + #[inline] fn from(graph_name: GraphName) -> Self { match graph_name { GraphName::NamedNode(node) => Self::NamedNode(node), @@ -552,11 +572,117 @@ impl From for GraphNameOrVariable { } } -impl From for GraphNameOrVariable { - fn from(graph_name: NamedNodeOrVariable) -> Self { +impl From for GraphNamePattern { + #[inline] + fn from(graph_name: NamedNodePattern) -> Self { match graph_name { - NamedNodeOrVariable::NamedNode(node) => Self::NamedNode(node), - NamedNodeOrVariable::Variable(var) => Self::Variable(var), + NamedNodePattern::NamedNode(node) => Self::NamedNode(node), + 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, + predicate: impl Into, + object: impl Into, + ) -> 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, + predicate: impl Into, + object: impl Into, + graph_name: impl Into, + ) -> 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 + ) } } }