From 969bb69fab02ea7ed6f83b0ad7b08c6a73f3d7d8 Mon Sep 17 00:00:00 2001 From: Tpt Date: Thu, 30 Sep 2021 19:21:51 +0200 Subject: [PATCH] Moves spargebra debug to regular debug ... ands adds to_sse() methods in order to be less surprising --- spargebra/src/algebra.rs | 430 +++++++++++++++++++++++++++------------ spargebra/src/parser.rs | 2 +- spargebra/src/query.rs | 46 +++-- spargebra/src/term.rs | 378 ++++++++++++++++++---------------- spargebra/src/update.rs | 80 +++++--- 5 files changed, 574 insertions(+), 362 deletions(-) diff --git a/spargebra/src/algebra.rs b/spargebra/src/algebra.rs index baf242e0..caace3a2 100644 --- a/spargebra/src/algebra.rs +++ b/spargebra/src/algebra.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), @@ -17,20 +17,50 @@ pub enum PropertyPathExpression { NegatedPropertySet(Vec), } -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 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), } -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), @@ -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, pub named: Option>, } -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 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, ")") +} diff --git a/spargebra/src/parser.rs b/spargebra/src/parser.rs index 64a5f6c1..4fd02af3 100644 --- a/spargebra/src/parser.rs +++ b/spargebra/src/parser.rs @@ -344,7 +344,7 @@ impl> From> for FocusedTripleOrPathPattern } } -#[derive(Eq, PartialEq, Clone, Hash)] +#[derive(Eq, PartialEq, Debug, Clone, Hash)] enum PartialGraphPattern { Optional(GraphPattern, Option), Minus(GraphPattern), diff --git a/spargebra/src/query.rs b/spargebra/src/query.rs index 9a300901..8bdd76f5 100644 --- a/spargebra/src/query.rs +++ b/spargebra/src/query.rs @@ -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 { 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, ")")?; } diff --git a/spargebra/src/term.rs b/spargebra/src/term.rs index 9ca85cf7..9fb4043f 100644 --- a/spargebra/src/term.rs +++ b/spargebra/src/term.rs @@ -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 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), } -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 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), } -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 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), } -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 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), } -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 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 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 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 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 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 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 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 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), } -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 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 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 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 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 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 { diff --git a/spargebra/src/update.rs b/spargebra/src/update.rs index c434f854..ad60535e 100644 --- a/spargebra/src/update.rs +++ b/spargebra/src/update.rs @@ -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>, @@ -33,16 +30,24 @@ impl Update { pub fn parse(update: &str, base_iri: Option<&str>) -> Result { 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 }, @@ -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, ")") } } }