Moves spargebra debug to regular debug

... ands adds to_sse() methods
in order to be less surprising
pull/171/head
Tpt 3 years ago
parent 9952f1256d
commit 969bb69fab
  1. 430
      spargebra/src/algebra.rs
  2. 2
      spargebra/src/parser.rs
  3. 46
      spargebra/src/query.rs
  4. 378
      spargebra/src/term.rs
  5. 80
      spargebra/src/update.rs

@ -5,7 +5,7 @@ use crate::term::*;
use std::fmt;
/// A [property path expression](https://www.w3.org/TR/sparql11-query/#defn_PropertyPathExpr)
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum PropertyPathExpression {
NamedNode(NamedNode),
Reverse(Box<Self>),
@ -17,20 +17,50 @@ pub enum PropertyPathExpression {
NegatedPropertySet(Vec<NamedNode>),
}
impl fmt::Debug for PropertyPathExpression {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl PropertyPathExpression {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
match self {
Self::NamedNode(p) => p.fmt(f),
Self::Reverse(p) => write!(f, "(reverse {:?})", p),
Self::Alternative(a, b) => write!(f, "(alt {:?} {:?})", a, b),
Self::Sequence(a, b) => write!(f, "(seq {:?} {:?})", a, b),
Self::ZeroOrMore(p) => write!(f, "(path* {:?})", p),
Self::OneOrMore(p) => write!(f, "(path+ {:?})", p),
Self::ZeroOrOne(p) => write!(f, "(path? {:?})", p),
Self::NamedNode(p) => p.fmt_sse(f),
Self::Reverse(p) => {
write!(f, "(reverse ")?;
p.fmt_sse(f)?;
write!(f, ")")
}
Self::Alternative(a, b) => {
write!(f, "(alt ")?;
a.fmt_sse(f)?;
write!(f, " ")?;
b.fmt_sse(f)?;
write!(f, ")")
}
Self::Sequence(a, b) => {
write!(f, "(seq ")?;
a.fmt_sse(f)?;
write!(f, " ")?;
b.fmt_sse(f)?;
write!(f, ")")
}
Self::ZeroOrMore(p) => {
write!(f, "(path* ")?;
p.fmt_sse(f)?;
write!(f, ")")
}
Self::OneOrMore(p) => {
write!(f, "(path+ ")?;
p.fmt_sse(f)?;
write!(f, ")")
}
Self::ZeroOrOne(p) => {
write!(f, "(path? ")?;
p.fmt_sse(f)?;
write!(f, ")")
}
Self::NegatedPropertySet(p) => {
write!(f, "(notoneof ")?;
write!(f, "(notoneof")?;
for p in p {
write!(f, " {:?}", p)?;
write!(f, " ")?;
p.fmt_sse(f)?;
}
write!(f, ")")
}
@ -69,7 +99,7 @@ impl From<NamedNode> for PropertyPathExpression {
}
/// An [expression](https://www.w3.org/TR/sparql11-query/#expressions)
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum Expression {
NamedNode(NamedNode),
Literal(Literal),
@ -116,48 +146,70 @@ pub enum Expression {
FunctionCall(Function, Vec<Self>),
}
impl fmt::Debug for Expression {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl Expression {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
match self {
Self::NamedNode(node) => node.fmt(f),
Self::Literal(l) => l.fmt(f),
Self::Variable(var) => var.fmt(f),
Self::Or(a, b) => write!(f, "(|| {:?} {:?})", a, b),
Self::And(a, b) => write!(f, "(&& {:?} {:?})", a, b),
Self::Equal(a, b) => write!(f, "(= {:?} {:?})", a, b),
Self::SameTerm(a, b) => write!(f, "(sameTerm {:?} {:?})", a, b),
Self::Greater(a, b) => write!(f, "(> {:?} {:?})", a, b),
Self::GreaterOrEqual(a, b) => write!(f, "(>= {:?} {:?})", a, b),
Self::Less(a, b) => write!(f, "(< {:?} {:?})", a, b),
Self::LessOrEqual(a, b) => write!(f, "(<= {:?} {:?})", a, b),
Self::NamedNode(node) => node.fmt_sse(f),
Self::Literal(l) => l.fmt_sse(f),
Self::Variable(var) => var.fmt_sse(f),
Self::Or(a, b) => fmt_sse_binary_expression(f, "||", a, b),
Self::And(a, b) => fmt_sse_binary_expression(f, "&&", a, b),
Self::Equal(a, b) => fmt_sse_binary_expression(f, "=", a, b),
Self::SameTerm(a, b) => fmt_sse_binary_expression(f, "sameTerm", a, b),
Self::Greater(a, b) => fmt_sse_binary_expression(f, ">", a, b),
Self::GreaterOrEqual(a, b) => fmt_sse_binary_expression(f, ">=", a, b),
Self::Less(a, b) => fmt_sse_binary_expression(f, "<", a, b),
Self::LessOrEqual(a, b) => fmt_sse_binary_expression(f, "<=", a, b),
Self::In(a, b) => {
write!(f, "(in {:?}", a)?;
write!(f, "(in ")?;
a.fmt_sse(f)?;
for p in b {
write!(f, " {:?}", p)?;
write!(f, " ")?;
p.fmt_sse(f)?;
}
write!(f, ")")
}
Self::Add(a, b) => write!(f, "(+ {:?} {:?})", a, b),
Self::Subtract(a, b) => write!(f, "(- {:?} {:?})", a, b),
Self::Multiply(a, b) => write!(f, "(* {:?} {:?})", a, b),
Self::Divide(a, b) => write!(f, "(/ {:?} {:?})", a, b),
Self::UnaryPlus(e) => write!(f, "(+ {:?})", e),
Self::UnaryMinus(e) => write!(f, "(- {:?})", e),
Self::Not(e) => write!(f, "(! {:?})", e),
Self::Add(a, b) => fmt_sse_binary_expression(f, "+", a, b),
Self::Subtract(a, b) => fmt_sse_binary_expression(f, "-", a, b),
Self::Multiply(a, b) => fmt_sse_binary_expression(f, "*", a, b),
Self::Divide(a, b) => fmt_sse_binary_expression(f, "/", a, b),
Self::UnaryPlus(e) => fmt_sse_unary_expression(f, "+", e),
Self::UnaryMinus(e) => fmt_sse_unary_expression(f, "-", e),
Self::Not(e) => fmt_sse_unary_expression(f, "!", e),
Self::FunctionCall(function, parameters) => {
write!(f, "({:?}", function)?;
write!(f, "( ")?;
function.fmt_sse(f)?;
for p in parameters {
write!(f, " {:?}", p)?;
write!(f, " ")?;
p.fmt_sse(f)?;
}
write!(f, ")")
}
Self::Exists(p) => write!(f, "(exists {:?})", p),
Self::Bound(v) => write!(f, "(bound {:?})", v),
Self::If(a, b, c) => write!(f, "(if {:?} {:?} {:?})", a, b, c),
Self::Exists(p) => {
write!(f, "(exists ")?;
p.fmt_sse(f)?;
write!(f, ")")
}
Self::Bound(v) => {
write!(f, "(bound ")?;
v.fmt_sse(f)?;
write!(f, ")")
}
Self::If(a, b, c) => {
write!(f, "(if ")?;
a.fmt_sse(f)?;
write!(f, " ")?;
b.fmt_sse(f)?;
write!(f, " ")?;
c.fmt_sse(f)?;
write!(f, ")")
}
Self::Coalesce(parameters) => {
write!(f, "(coalesce")?;
for p in parameters {
write!(f, " {:?}", p)?;
write!(f, " ")?;
p.fmt_sse(f)?;
}
write!(f, ")")
}
@ -269,7 +321,7 @@ fn write_arg_list(
}
/// A function name
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum Function {
Str,
Lang,
@ -330,8 +382,9 @@ pub enum Function {
Custom(NamedNode),
}
impl fmt::Debug for Function {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl Function {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
match self {
Self::Str => write!(f, "str"),
Self::Lang => write!(f, "lang"),
@ -389,7 +442,7 @@ impl fmt::Debug for Function {
Self::Object => write!(f, "object"),
#[cfg(feature = "rdf-star")]
Self::IsTriple => write!(f, "istriple"),
Self::Custom(iri) => iri.fmt(f),
Self::Custom(iri) => iri.fmt_sse(f),
}
}
}
@ -459,7 +512,7 @@ impl fmt::Display for Function {
}
/// A SPARQL query [graph pattern](https://www.w3.org/TR/sparql11-query/#sparqlQuery)
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum GraphPattern {
/// A [basic graph pattern](https://www.w3.org/TR/sparql11-query/#defn_BasicGraphPattern)
Bgp(Vec<TriplePattern>),
@ -535,13 +588,15 @@ pub enum GraphPattern {
},
}
impl fmt::Debug for GraphPattern {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl GraphPattern {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
match self {
Self::Bgp(p) => {
write!(f, "(bgp")?;
for pattern in p {
write!(f, " {:?}", pattern)?;
write!(f, " ")?;
pattern.fmt_sse(f)?;
}
write!(f, ")")
}
@ -549,41 +604,91 @@ impl fmt::Debug for GraphPattern {
subject,
path,
object,
} => write!(f, "(path {:?} {:?} {:?})", subject, path, object),
} => {
write!(f, "(path ")?;
subject.fmt_sse(f)?;
write!(f, " ")?;
path.fmt_sse(f)?;
write!(f, " ")?;
object.fmt_sse(f)?;
write!(f, ")")
}
Self::Sequence(elements) => {
write!(f, "(sequence")?;
for e in elements {
write!(f, " {:?}", e)?;
write!(f, " ")?;
e.fmt_sse(f)?;
}
write!(f, ")")
}
Self::Join { left, right } => write!(f, "(join {:?} {:?})", left, right),
Self::Join { left, right } => {
write!(f, "(join ")?;
left.fmt_sse(f)?;
write!(f, " ")?;
right.fmt_sse(f)?;
write!(f, ")")
}
Self::LeftJoin { left, right, expr } => {
write!(f, "(leftjoin ")?;
left.fmt_sse(f)?;
write!(f, " ")?;
right.fmt_sse(f)?;
if let Some(expr) = expr {
write!(f, "(leftjoin {:?} {:?} {:?})", left, right, expr)
} else {
write!(f, "(leftjoin {:?} {:?})", left, right)
write!(f, " ")?;
expr.fmt_sse(f)?;
}
write!(f, ")")
}
Self::Filter { expr, inner } => {
write!(f, "(filter ")?;
expr.fmt_sse(f)?;
write!(f, " ")?;
inner.fmt_sse(f)?;
write!(f, ")")
}
Self::Union { left, right } => {
write!(f, "(union ")?;
left.fmt_sse(f)?;
write!(f, " ")?;
right.fmt_sse(f)?;
write!(f, ")")
}
Self::Filter { expr, inner } => write!(f, "(filter {:?} {:?})", expr, inner),
Self::Union { left, right } => write!(f, "(union {:?} {:?})", left, right),
Self::Graph { graph_name, inner } => {
write!(f, "(graph {:?} {:?})", graph_name, inner)
write!(f, "(graph ")?;
graph_name.fmt_sse(f)?;
write!(f, " ")?;
inner.fmt_sse(f)?;
write!(f, ")")
}
Self::Extend { inner, var, expr } => {
write!(f, "(extend (({:?} {:?})) {:?})", var, expr, inner)
write!(f, "(extend ((")?;
var.fmt_sse(f)?;
write!(f, " ")?;
expr.fmt_sse(f)?;
write!(f, ")) ")?;
inner.fmt_sse(f)?;
write!(f, ")")
}
Self::Minus { left, right } => {
write!(f, "(minus ")?;
left.fmt_sse(f)?;
write!(f, " ")?;
right.fmt_sse(f)?;
write!(f, ")")
}
Self::Minus { left, right } => write!(f, "(minus {:?} {:?})", left, right),
Self::Service {
name,
pattern,
silent,
} => {
write!(f, "(service ")?;
if *silent {
write!(f, "(service silent {:?} {:?})", name, pattern)
} else {
write!(f, "(service {:?} {:?})", name, pattern)
write!(f, "silent ")?;
}
name.fmt_sse(f)?;
write!(f, " ")?;
pattern.fmt_sse(f)?;
write!(f, ")")
}
Self::Group {
inner,
@ -595,28 +700,39 @@ impl fmt::Debug for GraphPattern {
if i > 0 {
write!(f, " ")?;
}
write!(f, "{:?}", v)?;
v.fmt_sse(f)?;
}
write!(f, ") (")?;
for (i, (v, a)) in aggregates.iter().enumerate() {
if i > 0 {
write!(f, " ")?;
}
write!(f, "({:?} {:?})", a, v)?;
write!(f, "(")?;
a.fmt_sse(f)?;
write!(f, " ")?;
v.fmt_sse(f)?;
write!(f, ")")?;
}
write!(f, ") {:?})", inner)
write!(f, ") ")?;
inner.fmt_sse(f)?;
write!(f, ")")
}
Self::Table { variables, rows } => {
write!(f, "(table (vars")?;
for var in variables {
write!(f, " {:?}", var)?;
write!(f, " ")?;
var.fmt_sse(f)?;
}
write!(f, ")")?;
for row in rows {
write!(f, " (row")?;
for (value, var) in row.iter().zip(variables) {
if let Some(value) = value {
write!(f, " ({:?} {:?})", var, value)?;
write!(f, " (")?;
var.fmt_sse(f)?;
write!(f, " ")?;
value.fmt_sse(f)?;
write!(f, ")")?;
}
}
write!(f, ")")?;
@ -629,9 +745,11 @@ impl fmt::Debug for GraphPattern {
if i > 0 {
write!(f, " ")?;
}
write!(f, "{:?}", c)?;
c.fmt_sse(f)?;
}
write!(f, ") {:?})", inner)
write!(f, ") ")?;
inner.fmt_sse(f)?;
write!(f, ")")
}
Self::Project { inner, projection } => {
write!(f, "(project (")?;
@ -639,22 +757,34 @@ impl fmt::Debug for GraphPattern {
if i > 0 {
write!(f, " ")?;
}
write!(f, "{:?}", v)?;
v.fmt_sse(f)?;
}
write!(f, ") {:?})", inner)
write!(f, ") ")?;
inner.fmt_sse(f)?;
write!(f, ")")
}
Self::Distinct { inner } => {
write!(f, "(distinct ")?;
inner.fmt_sse(f)?;
write!(f, ")")
}
Self::Reduced { inner } => {
write!(f, "(reduced ")?;
inner.fmt_sse(f)?;
write!(f, ")")
}
Self::Distinct { inner } => write!(f, "(distinct {:?})", inner),
Self::Reduced { inner } => write!(f, "(reduced {:?})", inner),
Self::Slice {
inner,
start,
length,
} => {
if let Some(length) = length {
write!(f, "(slice {:?} {:?} {:?})", start, length, inner)
write!(f, "(slice {} {} ", start, length)?;
} else {
write!(f, "(slice {:?} _ {:?})", start, inner)
write!(f, "(slice {} _ ", start)?;
}
inner.fmt_sse(f)?;
write!(f, ")")
}
}
}
@ -963,7 +1093,7 @@ impl<'a> fmt::Display for SparqlGraphRootPattern<'a> {
}
/// A set function used in aggregates (c.f. [`GraphPattern::Group`])
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum AggregationFunction {
/// [Count](https://www.w3.org/TR/sparql11-query/#defn_aggCount)
Count {
@ -1009,88 +1139,90 @@ pub enum AggregationFunction {
},
}
impl fmt::Debug for AggregationFunction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl AggregationFunction {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
match self {
Self::Count { expr, distinct } => {
write!(f, "(sum")?;
if *distinct {
if let Some(expr) = expr {
write!(f, "(count distinct {:?})", expr)
} else {
write!(f, "(count distinct)")
}
} else if let Some(expr) = expr {
write!(f, "(count {:?})", expr)
} else {
write!(f, "(count)")
write!(f, " distinct")?;
}
if let Some(expr) = expr {
write!(f, " ")?;
expr.fmt_sse(f)?;
}
write!(f, ")")
}
Self::Sum { expr, distinct } => {
write!(f, "(sum ")?;
if *distinct {
write!(f, "(sum distinct {:?})", expr)
} else {
write!(f, "(sum {:?})", expr)
write!(f, "distinct ")?;
}
expr.fmt_sse(f)?;
write!(f, ")")
}
Self::Avg { expr, distinct } => {
write!(f, "(avg ")?;
if *distinct {
write!(f, "(avg distinct {:?})", expr)
} else {
write!(f, "(avg {:?})", expr)
write!(f, "distinct ")?;
}
expr.fmt_sse(f)?;
write!(f, ")")
}
Self::Min { expr, distinct } => {
write!(f, "(min ")?;
if *distinct {
write!(f, "(min distinct {:?})", expr)
} else {
write!(f, "(min {:?})", expr)
write!(f, "distinct ")?;
}
expr.fmt_sse(f)?;
write!(f, ")")
}
Self::Max { expr, distinct } => {
write!(f, "(max ")?;
if *distinct {
write!(f, "(max distinct {:?})", expr)
} else {
write!(f, "(max {:?})", expr)
write!(f, "distinct ")?;
}
expr.fmt_sse(f)?;
write!(f, ")")
}
Self::Sample { expr, distinct } => {
write!(f, "(sample ")?;
if *distinct {
write!(f, "(sample distinct {:?})", expr)
} else {
write!(f, "(sample {:?})", expr)
write!(f, "distinct ")?;
}
expr.fmt_sse(f)?;
write!(f, ")")
}
Self::GroupConcat {
expr,
distinct,
separator,
} => {
write!(f, "(group_concat ")?;
if *distinct {
if let Some(separator) = separator {
write!(f, "(group_concat distinct {:?} ", expr)?;
print_quoted_str(separator, f)?;
write!(f, ")")
} else {
write!(f, "(group_concat distinct {:?})", expr)
}
} else if let Some(separator) = separator {
write!(f, "(group_concat {:?} ", expr)?;
write!(f, "distinct ")?;
}
expr.fmt_sse(f)?;
if let Some(separator) = separator {
write!(f, " ")?;
print_quoted_str(separator, f)?;
write!(f, ")")
} else {
write!(f, "(group_concat {:?})", expr)
}
write!(f, ")")
}
Self::Custom {
name,
expr,
distinct,
} => {
write!(f, "(")?;
name.fmt_sse(f)?;
if *distinct {
write!(f, "({:?} distinct {:?})", name, expr)
} else {
write!(f, "({:?} {:?})", name, expr)
write!(f, " distinct")?;
}
write!(f, " ")?;
expr.fmt_sse(f)?;
write!(f, ")")
}
}
}
@ -1184,7 +1316,7 @@ impl fmt::Display for AggregationFunction {
}
/// An ordering comparator used by [`GraphPattern::OrderBy`]
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum OrderComparator {
/// Ascending order
Asc(Expression),
@ -1192,11 +1324,20 @@ pub enum OrderComparator {
Desc(Expression),
}
impl fmt::Debug for OrderComparator {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl OrderComparator {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
match self {
Self::Asc(e) => write!(f, "(asc {:?})", e),
Self::Desc(e) => write!(f, "(desc {:?})", e),
Self::Asc(e) => {
write!(f, "(asc ")?;
e.fmt_sse(f)?;
write!(f, ")")
}
Self::Desc(e) => {
write!(f, "(desc ")?;
e.fmt_sse(f)?;
write!(f, ")")
}
}
}
}
@ -1211,27 +1352,30 @@ impl fmt::Display for OrderComparator {
}
/// A SPARQL query [dataset specification](https://www.w3.org/TR/sparql11-query/#specifyingDataset)
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct QueryDataset {
pub default: Vec<NamedNode>,
pub named: Option<Vec<NamedNode>>,
}
impl fmt::Debug for QueryDataset {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl QueryDataset {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
write!(f, "(")?;
for (i, graph_name) in self.default.iter().enumerate() {
if i > 0 {
write!(f, " ")?;
}
write!(f, "{:?}", graph_name)?;
graph_name.fmt_sse(f)?;
}
if let Some(named) = &self.named {
for (i, graph_name) in named.iter().enumerate() {
if !self.default.is_empty() || i > 0 {
write!(f, " ")?;
}
write!(f, "(named {:?})", graph_name)?;
write!(f, "(named ")?;
graph_name.fmt_sse(f)?;
write!(f, ")")?;
}
}
write!(f, ")")
@ -1255,7 +1399,7 @@ impl fmt::Display for QueryDataset {
/// A target RDF graph for update operations
///
/// Could be a specific graph, all named graphs or the complete dataset.
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum GraphTarget {
NamedNode(NamedNode),
DefaultGraph,
@ -1263,10 +1407,11 @@ pub enum GraphTarget {
AllGraphs,
}
impl fmt::Debug for GraphTarget {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl GraphTarget {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
match self {
Self::NamedNode(node) => node.fmt(f),
Self::NamedNode(node) => node.fmt_sse(f),
Self::DefaultGraph => write!(f, "default"),
Self::NamedGraphs => write!(f, "named"),
Self::AllGraphs => write!(f, "all"),
@ -1299,3 +1444,24 @@ impl From<GraphName> for GraphTarget {
}
}
}
#[inline]
fn fmt_sse_unary_expression(f: &mut impl fmt::Write, name: &str, e: &Expression) -> fmt::Result {
write!(f, "({} ", name)?;
e.fmt_sse(f)?;
write!(f, ")")
}
#[inline]
fn fmt_sse_binary_expression(
f: &mut impl fmt::Write,
name: &str,
a: &Expression,
b: &Expression,
) -> fmt::Result {
write!(f, "({} ", name)?;
a.fmt_sse(f)?;
write!(f, " ")?;
b.fmt_sse(f)?;
write!(f, ")")
}

@ -344,7 +344,7 @@ impl<F, T: From<F>> From<FocusedTriplePattern<F>> for FocusedTripleOrPathPattern
}
}
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
enum PartialGraphPattern {
Optional(GraphPattern, Option<Expression>),
Minus(GraphPattern),

@ -8,19 +8,16 @@ use std::str::FromStr;
/// A parsed [SPARQL query](https://www.w3.org/TR/sparql11-query/)
///
/// The `Display` trait prints a serialization of the query using SPARQL syntax and
/// `Debug` prints the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
///
/// ```
/// use spargebra::Query;
///
/// let query_str = "SELECT ?s ?p ?o WHERE { ?s ?p ?o . }";
/// let query = Query::parse(query_str, None)?;
/// assert_eq!(query.to_string(), query_str);
/// assert_eq!(format!("{:?}", query), "(project (?s ?p ?o) (bgp (triple ?s ?p ?o)))");
/// assert_eq!(query.to_sse(), "(project (?s ?p ?o) (bgp (triple ?s ?p ?o)))");
/// # Result::Ok::<_, spargebra::ParseError>(())
/// ```
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum Query {
/// [SELECT](https://www.w3.org/TR/sparql11-query/#select)
Select {
@ -67,10 +64,17 @@ impl Query {
pub fn parse(query: &str, base_iri: Option<&str>) -> Result<Self, ParseError> {
parse_query(query, base_iri)
}
}
impl fmt::Debug for Query {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub fn to_sse(&self) -> String {
let mut buffer = String::new();
self.fmt_sse(&mut buffer)
.expect("Unexpected error during SSE formatting");
buffer
}
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
match self {
Query::Select {
dataset,
@ -81,9 +85,11 @@ impl fmt::Debug for Query {
write!(f, "(base <{}> ", base_iri)?;
}
if let Some(dataset) = dataset {
write!(f, "(dataset {:?} ", dataset)?;
write!(f, "(dataset ")?;
dataset.fmt_sse(f)?;
write!(f, " ")?;
}
write!(f, "{:?}", pattern)?;
pattern.fmt_sse(f)?;
if dataset.is_some() {
write!(f, ")")?;
}
@ -106,13 +112,15 @@ impl fmt::Debug for Query {
if i > 0 {
write!(f, " ")?;
}
write!(f, "{:?}", t)?;
t.fmt_sse(f)?;
}
write!(f, ") ")?;
if let Some(dataset) = dataset {
write!(f, "(dataset {:?} ", dataset)?;
write!(f, "(dataset ")?;
dataset.fmt_sse(f)?;
write!(f, " ")?;
}
write!(f, "{:?}", pattern)?;
pattern.fmt_sse(f)?;
if dataset.is_some() {
write!(f, ")")?;
}
@ -132,9 +140,11 @@ impl fmt::Debug for Query {
}
write!(f, "(describe ")?;
if let Some(dataset) = dataset {
write!(f, "(dataset {:?} ", dataset)?;
write!(f, "(dataset ")?;
dataset.fmt_sse(f)?;
write!(f, " ")?;
}
write!(f, "{:?}", pattern)?;
pattern.fmt_sse(f)?;
if dataset.is_some() {
write!(f, ")")?;
}
@ -154,9 +164,11 @@ impl fmt::Debug for Query {
}
write!(f, "(ask ")?;
if let Some(dataset) = dataset {
write!(f, "(dataset {:?} ", dataset)?;
write!(f, "(dataset ")?;
dataset.fmt_sse(f)?;
write!(f, " ")?;
}
write!(f, "{:?}", pattern)?;
pattern.fmt_sse(f)?;
if dataset.is_some() {
write!(f, ")")?;
}

@ -16,15 +16,15 @@ use std::fmt::Write;
/// NamedNode { iri: "http://example.com/foo".into() }.to_string()
/// )
/// ```
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Hash)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)]
pub struct NamedNode {
/// The [IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) itself.
pub iri: String,
}
impl fmt::Debug for NamedNode {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl NamedNode {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl Write) -> fmt::Result {
write!(f, "<{}>", self.iri)
}
}
@ -61,15 +61,15 @@ impl TryFrom<NamedNodePattern> for NamedNode {
/// BlankNode { id: "a1".into() }.to_string()
/// )
/// ```
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct BlankNode {
/// The [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier).
pub id: String,
}
impl fmt::Debug for BlankNode {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl BlankNode {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl Write) -> fmt::Result {
write!(f, "_:{}", self.id)
}
}
@ -106,7 +106,7 @@ impl fmt::Display for BlankNode {
/// Literal::LanguageTaggedString { value: "foo".into(), language: "en".into() }.to_string()
/// );
/// ```
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum Literal {
/// A [simple literal](https://www.w3.org/TR/rdf11-concepts/#dfn-simple-literal) without datatype or language form.
Simple {
@ -129,9 +129,9 @@ pub enum Literal {
},
}
impl fmt::Debug for Literal {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl Literal {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl Write) -> fmt::Result {
match self {
Literal::Simple { value } => print_quoted_str(value, f),
Literal::LanguageTaggedString { value, language } => {
@ -166,7 +166,7 @@ impl fmt::Display for Literal {
/// 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.
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum Subject {
NamedNode(NamedNode),
BlankNode(BlankNode),
@ -174,14 +174,14 @@ pub enum Subject {
Triple(Box<Triple>),
}
impl fmt::Debug for Subject {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl Subject {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl Write) -> fmt::Result {
match self {
Self::NamedNode(node) => node.fmt(f),
Self::BlankNode(node) => node.fmt(f),
Self::NamedNode(node) => node.fmt_sse(f),
Self::BlankNode(node) => node.fmt_sse(f),
#[cfg(feature = "rdf-star")]
Self::Triple(triple) => triple.fmt(f),
Self::Triple(triple) => triple.fmt_sse(f),
}
}
}
@ -242,20 +242,20 @@ impl TryFrom<TermPattern> for Subject {
/// The union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) and [triples](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple).
///
/// The default string formatter is returning an N-Triples, Turtle and SPARQL compatible representation.
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum GroundSubject {
NamedNode(NamedNode),
#[cfg(feature = "rdf-star")]
Triple(Box<GroundTriple>),
}
impl fmt::Debug for GroundSubject {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl GroundSubject {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl Write) -> fmt::Result {
match self {
Self::NamedNode(node) => node.fmt(f),
Self::NamedNode(node) => node.fmt_sse(f),
#[cfg(feature = "rdf-star")]
Self::Triple(triple) => triple.fmt(f),
Self::Triple(triple) => triple.fmt_sse(f),
}
}
}
@ -323,7 +323,7 @@ impl TryFrom<GroundTerm> for GroundSubject {
/// 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).
///
/// The default string formatter is returning an N-Triples, Turtle and SPARQL compatible representation.
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum Term {
NamedNode(NamedNode),
BlankNode(BlankNode),
@ -332,15 +332,15 @@ pub enum Term {
Triple(Box<Triple>),
}
impl fmt::Debug for Term {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl Term {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl Write) -> fmt::Result {
match self {
Self::NamedNode(node) => node.fmt(f),
Self::BlankNode(node) => node.fmt(f),
Self::Literal(literal) => literal.fmt(f),
Self::NamedNode(node) => node.fmt_sse(f),
Self::BlankNode(node) => node.fmt_sse(f),
Self::Literal(literal) => literal.fmt_sse(f),
#[cfg(feature = "rdf-star")]
Self::Triple(triple) => triple.fmt(f),
Self::Triple(triple) => triple.fmt_sse(f),
}
}
}
@ -422,7 +422,7 @@ impl TryFrom<TermPattern> for Term {
/// The union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri), [literals](https://www.w3.org/TR/rdf11-concepts/#dfn-literal) and [triples](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple).
///
/// The default string formatter is returning an N-Triples, Turtle and SPARQL compatible representation.
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum GroundTerm {
NamedNode(NamedNode),
Literal(Literal),
@ -430,14 +430,14 @@ pub enum GroundTerm {
Triple(Box<GroundTriple>),
}
impl fmt::Debug for GroundTerm {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl GroundTerm {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl Write) -> fmt::Result {
match self {
Self::NamedNode(node) => node.fmt(f),
Self::Literal(literal) => literal.fmt(f),
Self::NamedNode(node) => node.fmt_sse(f),
Self::Literal(literal) => literal.fmt_sse(f),
#[cfg(feature = "rdf-star")]
Self::Triple(triple) => triple.fmt(f),
Self::Triple(triple) => triple.fmt_sse(f),
}
}
}
@ -512,21 +512,23 @@ impl TryFrom<Term> for GroundTerm {
/// }.to_string()
/// )
/// ```
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct Triple {
pub subject: Subject,
pub predicate: NamedNode,
pub object: Term,
}
impl fmt::Debug for Triple {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"(triple {:?} {:?} {:?})",
self.subject, self.predicate, self.object
)
impl Triple {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl Write) -> fmt::Result {
write!(f, "(triple ")?;
self.subject.fmt_sse(f)?;
write!(f, " ")?;
self.predicate.fmt_sse(f)?;
write!(f, " ")?;
self.object.fmt_sse(f)?;
write!(f, ")")
}
}
@ -567,21 +569,23 @@ impl TryFrom<TriplePattern> for Triple {
/// }.to_string()
/// )
/// ```
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct GroundTriple {
pub subject: GroundSubject,
pub predicate: NamedNode,
pub object: GroundTerm,
}
impl fmt::Debug for GroundTriple {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"(triple {:?} {:?} {:?})",
self.subject, self.predicate, self.object
)
impl GroundTriple {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl Write) -> fmt::Result {
write!(f, "(triple ")?;
self.subject.fmt_sse(f)?;
write!(f, " ")?;
self.predicate.fmt_sse(f)?;
write!(f, " ")?;
self.object.fmt_sse(f)?;
write!(f, ")")
}
}
@ -608,17 +612,17 @@ impl TryFrom<Triple> for GroundTriple {
/// A possible graph name.
///
/// 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, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum GraphName {
NamedNode(NamedNode),
DefaultGraph,
}
impl fmt::Debug for GraphName {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl GraphName {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl Write) -> fmt::Result {
match self {
Self::NamedNode(node) => node.fmt(f),
Self::NamedNode(node) => node.fmt_sse(f),
Self::DefaultGraph => write!(f, "default"),
}
}
@ -672,7 +676,7 @@ impl TryFrom<GraphNamePattern> for GraphName {
/// }.to_string()
/// )
/// ```
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct Quad {
pub subject: Subject,
pub predicate: NamedNode,
@ -680,22 +684,25 @@ pub struct Quad {
pub graph_name: GraphName,
}
impl fmt::Debug for Quad {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.graph_name == GraphName::DefaultGraph {
write!(
f,
"(triple {:?} {:?} {:?})",
self.subject, self.predicate, self.object
)
} else {
write!(
f,
"(graph {:?} ((triple {:?} {:?} {:?})))",
self.graph_name, self.subject, self.predicate, self.object
)
impl Quad {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl Write) -> fmt::Result {
if self.graph_name != GraphName::DefaultGraph {
write!(f, "(graph ")?;
self.graph_name.fmt_sse(f)?;
write!(f, " (")?;
}
write!(f, "(triple ")?;
self.subject.fmt_sse(f)?;
write!(f, " ")?;
self.predicate.fmt_sse(f)?;
write!(f, " ")?;
self.object.fmt_sse(f)?;
write!(f, ")")?;
if self.graph_name != GraphName::DefaultGraph {
write!(f, "))")?;
}
Ok(())
}
}
@ -746,7 +753,7 @@ impl TryFrom<QuadPattern> for Quad {
/// }.to_string()
/// )
/// ```
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct GroundQuad {
pub subject: GroundSubject,
pub predicate: NamedNode,
@ -754,22 +761,25 @@ pub struct GroundQuad {
pub graph_name: GraphName,
}
impl fmt::Debug for GroundQuad {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.graph_name == GraphName::DefaultGraph {
write!(
f,
"(triple {:?} {:?} {:?})",
self.subject, self.predicate, self.object
)
} else {
write!(
f,
"(graph {:?} ((triple {:?} {:?} {:?})))",
self.graph_name, self.subject, self.predicate, self.object
)
impl GroundQuad {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl Write) -> fmt::Result {
if self.graph_name != GraphName::DefaultGraph {
write!(f, "(graph ")?;
self.graph_name.fmt_sse(f)?;
write!(f, " (")?;
}
write!(f, "(triple ")?;
self.subject.fmt_sse(f)?;
write!(f, " ")?;
self.predicate.fmt_sse(f)?;
write!(f, " ")?;
self.object.fmt_sse(f)?;
write!(f, ")")?;
if self.graph_name != GraphName::DefaultGraph {
write!(f, "))")?;
}
Ok(())
}
}
@ -812,14 +822,14 @@ impl TryFrom<Quad> for GroundQuad {
/// Variable { name: "foo".into() }.to_string()
/// );
/// ```
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Hash)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)]
pub struct Variable {
pub name: String,
}
impl fmt::Debug for Variable {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl Variable {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl Write) -> fmt::Result {
write!(f, "?{}", self.name)
}
}
@ -832,18 +842,18 @@ impl fmt::Display for Variable {
}
/// 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, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum NamedNodePattern {
NamedNode(NamedNode),
Variable(Variable),
}
impl fmt::Debug for NamedNodePattern {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl NamedNodePattern {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl Write) -> fmt::Result {
match self {
Self::NamedNode(node) => node.fmt(f),
Self::Variable(var) => var.fmt(f),
Self::NamedNode(node) => node.fmt_sse(f),
Self::Variable(var) => var.fmt_sse(f),
}
}
}
@ -873,7 +883,7 @@ impl From<Variable> for NamedNodePattern {
}
/// 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, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum TermPattern {
NamedNode(NamedNode),
BlankNode(BlankNode),
@ -883,16 +893,16 @@ pub enum TermPattern {
Variable(Variable),
}
impl fmt::Debug for TermPattern {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl TermPattern {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl Write) -> fmt::Result {
match self {
Self::NamedNode(term) => term.fmt(f),
Self::BlankNode(term) => term.fmt(f),
Self::Literal(term) => term.fmt(f),
Self::NamedNode(term) => term.fmt_sse(f),
Self::BlankNode(term) => term.fmt_sse(f),
Self::Literal(term) => term.fmt_sse(f),
#[cfg(feature = "rdf-star")]
Self::Triple(triple) => triple.fmt(f),
Self::Variable(var) => var.fmt(f),
Self::Triple(triple) => triple.fmt_sse(f),
Self::Variable(var) => var.fmt_sse(f),
}
}
}
@ -982,7 +992,7 @@ impl From<NamedNodePattern> for TermPattern {
}
/// 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, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum GroundTermPattern {
NamedNode(NamedNode),
Literal(Literal),
@ -990,14 +1000,14 @@ pub enum GroundTermPattern {
Triple(Box<GroundTriplePattern>),
}
impl fmt::Debug for GroundTermPattern {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl GroundTermPattern {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl Write) -> fmt::Result {
match self {
Self::NamedNode(term) => term.fmt(f),
Self::Literal(term) => term.fmt(f),
Self::Variable(var) => var.fmt(f),
Self::Triple(triple) => write!(f, "<<{}>>", triple),
Self::NamedNode(term) => term.fmt_sse(f),
Self::Literal(term) => term.fmt_sse(f),
Self::Variable(var) => var.fmt_sse(f),
Self::Triple(triple) => triple.fmt_sse(f),
}
}
}
@ -1091,20 +1101,20 @@ impl TryFrom<TermPattern> for GroundTermPattern {
}
/// 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, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum GraphNamePattern {
NamedNode(NamedNode),
DefaultGraph,
Variable(Variable),
}
impl fmt::Debug for GraphNamePattern {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl GraphNamePattern {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl Write) -> fmt::Result {
match self {
Self::NamedNode(node) => node.fmt(f),
Self::NamedNode(node) => node.fmt_sse(f),
Self::DefaultGraph => write!(f, "default"),
Self::Variable(var) => var.fmt(f),
Self::Variable(var) => var.fmt_sse(f),
}
}
}
@ -1155,7 +1165,7 @@ impl From<NamedNodePattern> for GraphNamePattern {
}
/// A [triple pattern](https://www.w3.org/TR/sparql11-query/#defn_TriplePattern)
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct TriplePattern {
pub subject: TermPattern,
pub predicate: NamedNodePattern,
@ -1176,14 +1186,16 @@ impl TriplePattern {
}
}
impl fmt::Debug for TriplePattern {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"(triple {:?} {:?} {:?})",
self.subject, self.predicate, self.object
)
impl TriplePattern {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl Write) -> fmt::Result {
write!(f, "(triple ")?;
self.subject.fmt_sse(f)?;
write!(f, " ")?;
self.predicate.fmt_sse(f)?;
write!(f, " ")?;
self.object.fmt_sse(f)?;
write!(f, ")")
}
}
@ -1206,21 +1218,23 @@ impl From<Triple> for TriplePattern {
}
/// A [triple pattern](https://www.w3.org/TR/sparql11-query/#defn_TriplePattern) without blank nodes
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct GroundTriplePattern {
pub subject: GroundTermPattern,
pub predicate: NamedNodePattern,
pub object: GroundTermPattern,
}
impl fmt::Debug for GroundTriplePattern {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"(triple {:?} {:?} {:?})",
self.subject, self.predicate, self.object
)
impl GroundTriplePattern {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl Write) -> fmt::Result {
write!(f, "(triple ")?;
self.subject.fmt_sse(f)?;
write!(f, " ")?;
self.predicate.fmt_sse(f)?;
write!(f, " ")?;
self.object.fmt_sse(f)?;
write!(f, ")")
}
}
@ -1256,7 +1270,7 @@ impl TryFrom<TriplePattern> for GroundTriplePattern {
}
/// A [triple pattern](https://www.w3.org/TR/sparql11-query/#defn_TriplePattern) in a specific graph
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct QuadPattern {
pub subject: TermPattern,
pub predicate: NamedNodePattern,
@ -1280,22 +1294,25 @@ impl QuadPattern {
}
}
impl fmt::Debug 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
)
impl QuadPattern {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl Write) -> fmt::Result {
if self.graph_name != GraphNamePattern::DefaultGraph {
write!(f, "(graph ")?;
self.graph_name.fmt_sse(f)?;
write!(f, " (")?;
}
write!(f, "(triple ")?;
self.subject.fmt_sse(f)?;
write!(f, " ")?;
self.predicate.fmt_sse(f)?;
write!(f, " ")?;
self.object.fmt_sse(f)?;
write!(f, ")")?;
if self.graph_name != GraphNamePattern::DefaultGraph {
write!(f, "))")?;
}
Ok(())
}
}
@ -1315,7 +1332,7 @@ impl fmt::Display for QuadPattern {
}
/// A [triple pattern](https://www.w3.org/TR/sparql11-query/#defn_TriplePattern) in a specific graph without blank nodes
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct GroundQuadPattern {
pub subject: GroundTermPattern,
pub predicate: NamedNodePattern,
@ -1323,22 +1340,25 @@ pub struct GroundQuadPattern {
pub graph_name: GraphNamePattern,
}
impl fmt::Debug 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
)
impl GroundQuadPattern {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub(crate) fn fmt_sse(&self, f: &mut impl Write) -> fmt::Result {
if self.graph_name != GraphNamePattern::DefaultGraph {
write!(f, "(graph ")?;
self.graph_name.fmt_sse(f)?;
write!(f, " (")?;
}
write!(f, "(triple ")?;
self.subject.fmt_sse(f)?;
write!(f, " ")?;
self.predicate.fmt_sse(f)?;
write!(f, " ")?;
self.object.fmt_sse(f)?;
write!(f, ")")?;
if self.graph_name != GraphNamePattern::DefaultGraph {
write!(f, "))")?;
}
Ok(())
}
}
@ -1372,7 +1392,7 @@ impl TryFrom<QuadPattern> for GroundQuadPattern {
}
#[inline]
pub(crate) fn print_quoted_str(string: &str, f: &mut fmt::Formatter<'_>) -> fmt::Result {
pub(crate) fn print_quoted_str(string: &str, f: &mut impl Write) -> fmt::Result {
f.write_char('"')?;
for c in string.chars() {
match c {

@ -8,19 +8,16 @@ use std::str::FromStr;
/// A parsed [SPARQL update](https://www.w3.org/TR/sparql11-update/)
///
/// The `Display` trait prints a serialization of the update using SPARQL syntax and
/// `Debug` prints the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
///
/// ```
/// use spargebra::Update;
///
/// let update_str = "CLEAR ALL ;";
/// let update = Update::parse(update_str, None)?;
/// assert_eq!(update.to_string().trim(), update_str);
/// assert_eq!(format!("{:?}", update), "(update (clear all))");
/// assert_eq!(update.to_sse(), "(update (clear all))");
/// # Result::Ok::<_, spargebra::ParseError>(())
/// ```
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct Update {
/// The update base IRI
pub base_iri: Option<Iri<String>>,
@ -33,16 +30,24 @@ impl Update {
pub fn parse(update: &str, base_iri: Option<&str>) -> Result<Self, ParseError> {
parse_update(update, base_iri)
}
}
impl fmt::Debug for Update {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
pub fn to_sse(&self) -> String {
let mut buffer = String::new();
self.fmt_sse(&mut buffer)
.expect("Unexpected error during SSE formatting");
buffer
}
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
if let Some(base_iri) = &self.base_iri {
write!(f, "(base <{}> ", base_iri)?;
}
write!(f, "(update")?;
for op in &self.operations {
write!(f, " {:?}", op)?;
write!(f, " ")?;
op.fmt_sse(f)?;
}
write!(f, ")")?;
if self.base_iri.is_some() {
@ -89,7 +94,7 @@ impl<'a> TryFrom<&'a String> for Update {
}
/// The [graph update operations](https://www.w3.org/TR/sparql11-update/#formalModelGraphUpdate)
#[derive(Eq, PartialEq, Clone, Hash)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum GraphUpdateOperation {
/// [insert data](https://www.w3.org/TR/sparql11-update/#defn_insertDataOperation)
InsertData { data: Vec<Quad> },
@ -116,8 +121,9 @@ pub enum GraphUpdateOperation {
Drop { silent: bool, graph: GraphTarget },
}
impl fmt::Debug for GraphUpdateOperation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl GraphUpdateOperation {
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
match self {
GraphUpdateOperation::InsertData { data } => {
write!(f, "(insertData (")?;
@ -125,7 +131,7 @@ impl fmt::Debug for GraphUpdateOperation {
if i > 0 {
write!(f, " ")?;
}
write!(f, "{:?}", t)?;
t.fmt_sse(f)?;
}
write!(f, "))")
}
@ -135,7 +141,7 @@ impl fmt::Debug for GraphUpdateOperation {
if i > 0 {
write!(f, " ")?;
}
write!(f, "{:?}", t)?;
t.fmt_sse(f)?;
}
write!(f, "))")
}
@ -145,13 +151,15 @@ impl fmt::Debug for GraphUpdateOperation {
using,
pattern,
} => {
write!(f, "(modify")?;
write!(f, "(modify ")?;
if let Some(using) = using {
write!(f, " (using {:?}", using)?;
}
write!(f, " {:?}", pattern)?;
if using.is_some() {
write!(f, " (using ")?;
using.fmt_sse(f)?;
write!(f, " ")?;
pattern.fmt_sse(f)?;
write!(f, ")")?;
} else {
pattern.fmt_sse(f)?;
}
if !delete.is_empty() {
write!(f, " (delete (")?;
@ -159,7 +167,7 @@ impl fmt::Debug for GraphUpdateOperation {
if i > 0 {
write!(f, " ")?;
}
write!(f, "{:?}", t)?;
t.fmt_sse(f)?;
}
write!(f, "))")?;
}
@ -169,39 +177,45 @@ impl fmt::Debug for GraphUpdateOperation {
if i > 0 {
write!(f, " ")?;
}
write!(f, "{:?}", t)?;
t.fmt_sse(f)?;
}
write!(f, "))")?;
}
write!(f, ")")
}
GraphUpdateOperation::Load { silent, from, to } => {
write!(f, "(load")?;
write!(f, "(load ")?;
if *silent {
write!(f, " silent")?;
write!(f, "silent ")?;
}
write!(f, " {:?} {:?}", from, to)
from.fmt_sse(f)?;
write!(f, " ")?;
to.fmt_sse(f)?;
write!(f, ")")
}
GraphUpdateOperation::Clear { silent, graph } => {
write!(f, "(clear")?;
write!(f, "(clear ")?;
if *silent {
write!(f, " silent")?;
write!(f, "silent ")?;
}
write!(f, " {:?})", graph)
graph.fmt_sse(f)?;
write!(f, ")")
}
GraphUpdateOperation::Create { silent, graph } => {
write!(f, "(create")?;
write!(f, "(create ")?;
if *silent {
write!(f, " silent")?;
write!(f, "silent ")?;
}
write!(f, " {:?})", graph)
graph.fmt_sse(f)?;
write!(f, ")")
}
GraphUpdateOperation::Drop { silent, graph } => {
write!(f, "(drop")?;
write!(f, "(drop ")?;
if *silent {
write!(f, " silent")?;
write!(f, "silent ")?;
}
write!(f, " {:?})", graph)
graph.fmt_sse(f)?;
write!(f, ")")
}
}
}

Loading…
Cancel
Save