1use crate::term::*;
4use oxrdf::LiteralRef;
5use std::fmt;
6
7#[derive(Eq, PartialEq, Debug, Clone, Hash)]
9pub enum PropertyPathExpression {
10 NamedNode(NamedNode),
11 Reverse(Box<Self>),
12 Sequence(Box<Self>, Box<Self>),
13 Alternative(Box<Self>, Box<Self>),
14 ZeroOrMore(Box<Self>),
15 OneOrMore(Box<Self>),
16 ZeroOrOne(Box<Self>),
17 NegatedPropertySet(Vec<NamedNode>),
18}
19
20impl PropertyPathExpression {
21 pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
23 match self {
24 Self::NamedNode(p) => write!(f, "{p}"),
25 Self::Reverse(p) => {
26 f.write_str("(reverse ")?;
27 p.fmt_sse(f)?;
28 f.write_str(")")
29 }
30 Self::Alternative(a, b) => {
31 f.write_str("(alt ")?;
32 a.fmt_sse(f)?;
33 f.write_str(" ")?;
34 b.fmt_sse(f)?;
35 f.write_str(")")
36 }
37 Self::Sequence(a, b) => {
38 f.write_str("(seq ")?;
39 a.fmt_sse(f)?;
40 f.write_str(" ")?;
41 b.fmt_sse(f)?;
42 f.write_str(")")
43 }
44 Self::ZeroOrMore(p) => {
45 f.write_str("(path* ")?;
46 p.fmt_sse(f)?;
47 f.write_str(")")
48 }
49 Self::OneOrMore(p) => {
50 f.write_str("(path+ ")?;
51 p.fmt_sse(f)?;
52 f.write_str(")")
53 }
54 Self::ZeroOrOne(p) => {
55 f.write_str("(path? ")?;
56 p.fmt_sse(f)?;
57 f.write_str(")")
58 }
59 Self::NegatedPropertySet(p) => {
60 f.write_str("(notoneof")?;
61 for p in p {
62 write!(f, " {p}")?;
63 }
64 f.write_str(")")
65 }
66 }
67 }
68}
69
70impl fmt::Display for PropertyPathExpression {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 match self {
73 Self::NamedNode(p) => p.fmt(f),
74 Self::Reverse(p) => write!(f, "^({p})"),
75 Self::Sequence(a, b) => write!(f, "({a} / {b})"),
76 Self::Alternative(a, b) => write!(f, "({a} | {b})"),
77 Self::ZeroOrMore(p) => write!(f, "({p})*"),
78 Self::OneOrMore(p) => write!(f, "({p})+"),
79 Self::ZeroOrOne(p) => write!(f, "({p})?"),
80 Self::NegatedPropertySet(p) => {
81 f.write_str("!(")?;
82 for (i, c) in p.iter().enumerate() {
83 if i > 0 {
84 f.write_str(" | ")?;
85 }
86 write!(f, "{c}")?;
87 }
88 f.write_str(")")
89 }
90 }
91 }
92}
93
94impl From<NamedNode> for PropertyPathExpression {
95 fn from(p: NamedNode) -> Self {
96 Self::NamedNode(p)
97 }
98}
99
100#[derive(Eq, PartialEq, Debug, Clone, Hash)]
102pub enum Expression {
103 NamedNode(NamedNode),
104 Literal(Literal),
105 Variable(Variable),
106 Or(Box<Self>, Box<Self>),
108 And(Box<Self>, Box<Self>),
110 Equal(Box<Self>, Box<Self>),
112 SameTerm(Box<Self>, Box<Self>),
114 Greater(Box<Self>, Box<Self>),
116 GreaterOrEqual(Box<Self>, Box<Self>),
117 Less(Box<Self>, Box<Self>),
119 LessOrEqual(Box<Self>, Box<Self>),
120 In(Box<Self>, Vec<Self>),
122 Add(Box<Self>, Box<Self>),
124 Subtract(Box<Self>, Box<Self>),
126 Multiply(Box<Self>, Box<Self>),
128 Divide(Box<Self>, Box<Self>),
130 UnaryPlus(Box<Self>),
132 UnaryMinus(Box<Self>),
134 Not(Box<Self>),
136 Exists(Box<GraphPattern>),
138 Bound(Variable),
140 If(Box<Self>, Box<Self>, Box<Self>),
142 Coalesce(Vec<Self>),
144 FunctionCall(Function, Vec<Self>),
146}
147
148impl Expression {
149 pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
151 match self {
152 Self::NamedNode(node) => write!(f, "{node}"),
153 Self::Literal(l) => write!(f, "{l}"),
154 Self::Variable(var) => write!(f, "{var}"),
155 Self::Or(a, b) => fmt_sse_binary_expression(f, "||", a, b),
156 Self::And(a, b) => fmt_sse_binary_expression(f, "&&", a, b),
157 Self::Equal(a, b) => fmt_sse_binary_expression(f, "=", a, b),
158 Self::SameTerm(a, b) => fmt_sse_binary_expression(f, "sameTerm", a, b),
159 Self::Greater(a, b) => fmt_sse_binary_expression(f, ">", a, b),
160 Self::GreaterOrEqual(a, b) => fmt_sse_binary_expression(f, ">=", a, b),
161 Self::Less(a, b) => fmt_sse_binary_expression(f, "<", a, b),
162 Self::LessOrEqual(a, b) => fmt_sse_binary_expression(f, "<=", a, b),
163 Self::In(a, b) => {
164 f.write_str("(in ")?;
165 a.fmt_sse(f)?;
166 for p in b {
167 f.write_str(" ")?;
168 p.fmt_sse(f)?;
169 }
170 f.write_str(")")
171 }
172 Self::Add(a, b) => fmt_sse_binary_expression(f, "+", a, b),
173 Self::Subtract(a, b) => fmt_sse_binary_expression(f, "-", a, b),
174 Self::Multiply(a, b) => fmt_sse_binary_expression(f, "*", a, b),
175 Self::Divide(a, b) => fmt_sse_binary_expression(f, "/", a, b),
176 Self::UnaryPlus(e) => fmt_sse_unary_expression(f, "+", e),
177 Self::UnaryMinus(e) => fmt_sse_unary_expression(f, "-", e),
178 Self::Not(e) => fmt_sse_unary_expression(f, "!", e),
179 Self::FunctionCall(function, parameters) => {
180 f.write_str("( ")?;
181 function.fmt_sse(f)?;
182 for p in parameters {
183 f.write_str(" ")?;
184 p.fmt_sse(f)?;
185 }
186 f.write_str(")")
187 }
188 Self::Exists(p) => {
189 f.write_str("(exists ")?;
190 p.fmt_sse(f)?;
191 f.write_str(")")
192 }
193 Self::Bound(v) => {
194 write!(f, "(bound {v})")
195 }
196 Self::If(a, b, c) => {
197 f.write_str("(if ")?;
198 a.fmt_sse(f)?;
199 f.write_str(" ")?;
200 b.fmt_sse(f)?;
201 f.write_str(" ")?;
202 c.fmt_sse(f)?;
203 f.write_str(")")
204 }
205 Self::Coalesce(parameters) => {
206 f.write_str("(coalesce")?;
207 for p in parameters {
208 f.write_str(" ")?;
209 p.fmt_sse(f)?;
210 }
211 f.write_str(")")
212 }
213 }
214 }
215
216 fn walk<'a>(&'a self, callback: &mut impl FnMut(&'a Self)) {
217 callback(self);
218 match self {
219 Self::Variable(_)
220 | Self::Bound(_)
221 | Self::NamedNode(_)
222 | Self::Literal(_)
223 | Self::Exists(_) => (),
224 Self::UnaryPlus(i) | Self::UnaryMinus(i) | Self::Not(i) => i.walk(callback),
225 Self::Or(l, r)
226 | Self::And(l, r)
227 | Self::Equal(l, r)
228 | Self::SameTerm(l, r)
229 | Self::Greater(l, r)
230 | Self::GreaterOrEqual(l, r)
231 | Self::Less(l, r)
232 | Self::LessOrEqual(l, r)
233 | Self::Add(l, r)
234 | Self::Subtract(l, r)
235 | Self::Multiply(l, r)
236 | Self::Divide(l, r) => {
237 l.walk(callback);
238 r.walk(callback);
239 }
240 Self::If(c, l, r) => {
241 c.walk(callback);
242 l.walk(callback);
243 r.walk(callback);
244 }
245 Self::Coalesce(l) | Self::FunctionCall(_, l) => {
246 for e in l {
247 e.walk(callback);
248 }
249 }
250 Self::In(l, r) => {
251 l.walk(callback);
252 for e in r {
253 e.walk(callback);
254 }
255 }
256 }
257 }
258
259 fn lookup_used_variable<'a>(&'a self, callback: &mut impl FnMut(&'a Variable)) {
260 self.walk(&mut |e| {
261 if let Self::Variable(v) | Self::Bound(v) = e {
262 callback(v)
263 } else if let Self::Exists(p) = e {
264 p.lookup_used_variables(callback)
265 }
266 })
267 }
268}
269
270impl fmt::Display for Expression {
271 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
272 match self {
273 Self::NamedNode(node) => node.fmt(f),
274 Self::Literal(l) => l.fmt(f),
275 Self::Variable(var) => var.fmt(f),
276 Self::Or(a, b) => write!(f, "({a} || {b})"),
277 Self::And(a, b) => write!(f, "({a} && {b})"),
278 Self::Equal(a, b) => {
279 write!(f, "({a} = {b})")
280 }
281 Self::SameTerm(a, b) => {
282 write!(f, "sameTerm({a}, {b})")
283 }
284 Self::Greater(a, b) => {
285 write!(f, "({a} > {b})")
286 }
287 Self::GreaterOrEqual(a, b) => write!(f, "({a} >= {b})"),
288 Self::Less(a, b) => {
289 write!(f, "({a} < {b})")
290 }
291 Self::LessOrEqual(a, b) => write!(f, "({a} <= {b})"),
292 Self::In(a, b) => {
293 write!(f, "({a} IN ")?;
294 write_arg_list(b, f)?;
295 f.write_str(")")
296 }
297 Self::Add(a, b) => {
298 write!(f, "{a} + {b}")
299 }
300 Self::Subtract(a, b) => {
301 write!(f, "{a} - {b}")
302 }
303 Self::Multiply(a, b) => {
304 write!(f, "{a} * {b}")
305 }
306 Self::Divide(a, b) => {
307 write!(f, "{a} / {b}")
308 }
309 Self::UnaryPlus(e) => write!(f, "+{e}"),
310 Self::UnaryMinus(e) => write!(f, "-{e}"),
311 Self::Not(e) => match e.as_ref() {
312 Self::Exists(p) => write!(f, "NOT EXISTS {{ {p} }}"),
313 e => write!(f, "!{e}"),
314 },
315 Self::FunctionCall(function, parameters) => {
316 write!(f, "{function}")?;
317 write_arg_list(parameters, f)
318 }
319 Self::Bound(v) => write!(f, "BOUND({v})"),
320 Self::Exists(p) => write!(f, "EXISTS {{ {p} }}"),
321 Self::If(a, b, c) => write!(f, "IF({a}, {b}, {c})"),
322 Self::Coalesce(parameters) => {
323 f.write_str("COALESCE")?;
324 write_arg_list(parameters, f)
325 }
326 }
327 }
328}
329
330impl From<NamedNode> for Expression {
331 fn from(p: NamedNode) -> Self {
332 Self::NamedNode(p)
333 }
334}
335
336impl From<Literal> for Expression {
337 fn from(p: Literal) -> Self {
338 Self::Literal(p)
339 }
340}
341
342impl From<Variable> for Expression {
343 fn from(v: Variable) -> Self {
344 Self::Variable(v)
345 }
346}
347
348impl From<NamedNodePattern> for Expression {
349 fn from(p: NamedNodePattern) -> Self {
350 match p {
351 NamedNodePattern::NamedNode(p) => p.into(),
352 NamedNodePattern::Variable(p) => p.into(),
353 }
354 }
355}
356
357fn write_arg_list(
358 params: impl IntoIterator<Item = impl fmt::Display>,
359 f: &mut fmt::Formatter<'_>,
360) -> fmt::Result {
361 f.write_str("(")?;
362 let mut cont = false;
363 for p in params {
364 if cont {
365 f.write_str(", ")?;
366 }
367 p.fmt(f)?;
368 cont = true;
369 }
370 f.write_str(")")
371}
372
373#[derive(Eq, PartialEq, Debug, Clone, Hash)]
375pub enum Function {
376 Str,
377 Lang,
378 LangMatches,
379 Datatype,
380 Iri,
381 BNode,
382 Rand,
383 Abs,
384 Ceil,
385 Floor,
386 Round,
387 Concat,
388 SubStr,
389 StrLen,
390 Replace,
391 UCase,
392 LCase,
393 EncodeForUri,
394 Contains,
395 StrStarts,
396 StrEnds,
397 StrBefore,
398 StrAfter,
399 Year,
400 Month,
401 Day,
402 Hours,
403 Minutes,
404 Seconds,
405 Timezone,
406 Tz,
407 Now,
408 Uuid,
409 StrUuid,
410 Md5,
411 Sha1,
412 Sha256,
413 Sha384,
414 Sha512,
415 StrLang,
416 StrDt,
417 IsIri,
418 IsBlank,
419 IsLiteral,
420 IsNumeric,
421 Regex,
422 #[cfg(feature = "sparql-12")]
423 Triple,
424 #[cfg(feature = "sparql-12")]
425 Subject,
426 #[cfg(feature = "sparql-12")]
427 Predicate,
428 #[cfg(feature = "sparql-12")]
429 Object,
430 #[cfg(feature = "sparql-12")]
431 IsTriple,
432 #[cfg(feature = "sparql-12")]
433 LangDir,
434 #[cfg(feature = "sparql-12")]
435 HasLang,
436 #[cfg(feature = "sparql-12")]
437 HasLangDir,
438 #[cfg(feature = "sparql-12")]
439 StrLangDir,
440 #[cfg(feature = "sep-0002")]
441 Adjust,
442 Custom(NamedNode),
443}
444
445impl Function {
446 pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
448 match self {
449 Self::Str => f.write_str("str"),
450 Self::Lang => f.write_str("lang"),
451 Self::LangMatches => f.write_str("langmatches"),
452 Self::Datatype => f.write_str("datatype"),
453 Self::Iri => f.write_str("iri"),
454 Self::BNode => f.write_str("bnode"),
455 Self::Rand => f.write_str("rand"),
456 Self::Abs => f.write_str("abs"),
457 Self::Ceil => f.write_str("ceil"),
458 Self::Floor => f.write_str("floor"),
459 Self::Round => f.write_str("round"),
460 Self::Concat => f.write_str("concat"),
461 Self::SubStr => f.write_str("substr"),
462 Self::StrLen => f.write_str("strlen"),
463 Self::Replace => f.write_str("replace"),
464 Self::UCase => f.write_str("ucase"),
465 Self::LCase => f.write_str("lcase"),
466 Self::EncodeForUri => f.write_str("encode_for_uri"),
467 Self::Contains => f.write_str("contains"),
468 Self::StrStarts => f.write_str("strstarts"),
469 Self::StrEnds => f.write_str("strends"),
470 Self::StrBefore => f.write_str("strbefore"),
471 Self::StrAfter => f.write_str("strafter"),
472 Self::Year => f.write_str("year"),
473 Self::Month => f.write_str("month"),
474 Self::Day => f.write_str("day"),
475 Self::Hours => f.write_str("hours"),
476 Self::Minutes => f.write_str("minutes"),
477 Self::Seconds => f.write_str("seconds"),
478 Self::Timezone => f.write_str("timezone"),
479 Self::Tz => f.write_str("tz"),
480 Self::Now => f.write_str("now"),
481 Self::Uuid => f.write_str("uuid"),
482 Self::StrUuid => f.write_str("struuid"),
483 Self::Md5 => f.write_str("md5"),
484 Self::Sha1 => f.write_str("sha1"),
485 Self::Sha256 => f.write_str("sha256"),
486 Self::Sha384 => f.write_str("sha384"),
487 Self::Sha512 => f.write_str("sha512"),
488 Self::StrLang => f.write_str("strlang"),
489 Self::StrDt => f.write_str("strdt"),
490 Self::IsIri => f.write_str("isiri"),
491 Self::IsBlank => f.write_str("isblank"),
492 Self::IsLiteral => f.write_str("isliteral"),
493 Self::IsNumeric => f.write_str("isnumeric"),
494 Self::Regex => f.write_str("regex"),
495 #[cfg(feature = "sparql-12")]
496 Self::Triple => f.write_str("triple"),
497 #[cfg(feature = "sparql-12")]
498 Self::Subject => f.write_str("subject"),
499 #[cfg(feature = "sparql-12")]
500 Self::Predicate => f.write_str("predicate"),
501 #[cfg(feature = "sparql-12")]
502 Self::Object => f.write_str("object"),
503 #[cfg(feature = "sparql-12")]
504 Self::IsTriple => f.write_str("istriple"),
505 #[cfg(feature = "sparql-12")]
506 Function::LangDir => f.write_str("langdir"),
507 #[cfg(feature = "sparql-12")]
508 Function::HasLang => f.write_str("haslang"),
509 #[cfg(feature = "sparql-12")]
510 Function::HasLangDir => f.write_str("haslangdir"),
511 #[cfg(feature = "sparql-12")]
512 Function::StrLangDir => f.write_str("strlangdir"),
513 #[cfg(feature = "sep-0002")]
514 Self::Adjust => f.write_str("adjust"),
515 Self::Custom(iri) => write!(f, "{iri}"),
516 }
517 }
518}
519
520impl fmt::Display for Function {
521 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
522 match self {
523 Self::Str => f.write_str("STR"),
524 Self::Lang => f.write_str("LANG"),
525 Self::LangMatches => f.write_str("LANGMATCHES"),
526 Self::Datatype => f.write_str("DATATYPE"),
527 Self::Iri => f.write_str("IRI"),
528 Self::BNode => f.write_str("BNODE"),
529 Self::Rand => f.write_str("RAND"),
530 Self::Abs => f.write_str("ABS"),
531 Self::Ceil => f.write_str("CEIL"),
532 Self::Floor => f.write_str("FLOOR"),
533 Self::Round => f.write_str("ROUND"),
534 Self::Concat => f.write_str("CONCAT"),
535 Self::SubStr => f.write_str("SUBSTR"),
536 Self::StrLen => f.write_str("STRLEN"),
537 Self::Replace => f.write_str("REPLACE"),
538 Self::UCase => f.write_str("UCASE"),
539 Self::LCase => f.write_str("LCASE"),
540 Self::EncodeForUri => f.write_str("ENCODE_FOR_URI"),
541 Self::Contains => f.write_str("CONTAINS"),
542 Self::StrStarts => f.write_str("STRSTARTS"),
543 Self::StrEnds => f.write_str("STRENDS"),
544 Self::StrBefore => f.write_str("STRBEFORE"),
545 Self::StrAfter => f.write_str("STRAFTER"),
546 Self::Year => f.write_str("YEAR"),
547 Self::Month => f.write_str("MONTH"),
548 Self::Day => f.write_str("DAY"),
549 Self::Hours => f.write_str("HOURS"),
550 Self::Minutes => f.write_str("MINUTES"),
551 Self::Seconds => f.write_str("SECONDS"),
552 Self::Timezone => f.write_str("TIMEZONE"),
553 Self::Tz => f.write_str("TZ"),
554 Self::Now => f.write_str("NOW"),
555 Self::Uuid => f.write_str("UUID"),
556 Self::StrUuid => f.write_str("STRUUID"),
557 Self::Md5 => f.write_str("MD5"),
558 Self::Sha1 => f.write_str("SHA1"),
559 Self::Sha256 => f.write_str("SHA256"),
560 Self::Sha384 => f.write_str("SHA384"),
561 Self::Sha512 => f.write_str("SHA512"),
562 Self::StrLang => f.write_str("STRLANG"),
563 Self::StrDt => f.write_str("STRDT"),
564 Self::IsIri => f.write_str("isIRI"),
565 Self::IsBlank => f.write_str("isBLANK"),
566 Self::IsLiteral => f.write_str("isLITERAL"),
567 Self::IsNumeric => f.write_str("isNUMERIC"),
568 Self::Regex => f.write_str("REGEX"),
569 #[cfg(feature = "sparql-12")]
570 Self::Triple => f.write_str("TRIPLE"),
571 #[cfg(feature = "sparql-12")]
572 Self::Subject => f.write_str("SUBJECT"),
573 #[cfg(feature = "sparql-12")]
574 Self::Predicate => f.write_str("PREDICATE"),
575 #[cfg(feature = "sparql-12")]
576 Self::Object => f.write_str("OBJECT"),
577 #[cfg(feature = "sparql-12")]
578 Self::IsTriple => f.write_str("isTRIPLE"),
579 #[cfg(feature = "sparql-12")]
580 Function::LangDir => f.write_str("LANGDIR"),
581 #[cfg(feature = "sparql-12")]
582 Function::HasLang => f.write_str("hasLANG"),
583 #[cfg(feature = "sparql-12")]
584 Function::HasLangDir => f.write_str("hasLANGDIR"),
585 #[cfg(feature = "sparql-12")]
586 Function::StrLangDir => f.write_str("STRLANGDIR"),
587 #[cfg(feature = "sep-0002")]
588 Self::Adjust => f.write_str("ADJUST"),
589 Self::Custom(iri) => iri.fmt(f),
590 }
591 }
592}
593
594#[derive(Eq, PartialEq, Debug, Clone, Hash)]
596pub enum GraphPattern {
597 Bgp { patterns: Vec<TriplePattern> },
599 Path {
601 subject: TermPattern,
602 path: PropertyPathExpression,
603 object: TermPattern,
604 },
605 Join { left: Box<Self>, right: Box<Self> },
607 LeftJoin {
609 left: Box<Self>,
610 right: Box<Self>,
611 expression: Option<Expression>,
612 },
613 #[cfg(feature = "sep-0006")]
615 Lateral { left: Box<Self>, right: Box<Self> },
616 Filter { expr: Expression, inner: Box<Self> },
618 Union { left: Box<Self>, right: Box<Self> },
620 Graph {
621 name: NamedNodePattern,
622 inner: Box<Self>,
623 },
624 Extend {
626 inner: Box<Self>,
627 variable: Variable,
628 expression: Expression,
629 },
630 Minus { left: Box<Self>, right: Box<Self> },
632 Values {
634 variables: Vec<Variable>,
635 bindings: Vec<Vec<Option<GroundTerm>>>,
636 },
637 OrderBy {
639 inner: Box<Self>,
640 expression: Vec<OrderExpression>,
641 },
642 Project {
644 inner: Box<Self>,
645 variables: Vec<Variable>,
646 },
647 Distinct { inner: Box<Self> },
649 Reduced { inner: Box<Self> },
651 Slice {
653 inner: Box<Self>,
654 start: usize,
655 length: Option<usize>,
656 },
657 Group {
659 inner: Box<Self>,
660 variables: Vec<Variable>,
661 aggregates: Vec<(Variable, AggregateExpression)>,
662 },
663 Service {
665 name: NamedNodePattern,
666 inner: Box<Self>,
667 silent: bool,
668 },
669}
670
671impl fmt::Display for GraphPattern {
672 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
673 match self {
674 Self::Bgp { patterns } => {
675 for pattern in patterns {
676 write!(f, "{pattern} .")?
677 }
678 Ok(())
679 }
680 Self::Path {
681 subject,
682 path,
683 object,
684 } => write!(f, "{subject} {path} {object} ."),
685 Self::Join { left, right } => {
686 match right.as_ref() {
687 Self::LeftJoin { .. }
688 | Self::Minus { .. }
689 | Self::Extend { .. }
690 | Self::Filter { .. } => {
691 write!(f, "{left} {{ {right} }}")
693 }
694 #[cfg(feature = "sep-0006")]
695 Self::Lateral { .. } => {
696 write!(f, "{left} {{ {right} }}")
697 }
698 _ => write!(f, "{left} {right}"),
699 }
700 }
701 Self::LeftJoin {
702 left,
703 right,
704 expression,
705 } => {
706 if let Some(expr) = expression {
707 write!(f, "{left} OPTIONAL {{ {right} FILTER({expr}) }}")
708 } else {
709 write!(f, "{left} OPTIONAL {{ {right} }}")
710 }
711 }
712 #[cfg(feature = "sep-0006")]
713 Self::Lateral { left, right } => {
714 write!(f, "{left} LATERAL {{ {right} }}")
715 }
716 Self::Filter { expr, inner } => {
717 write!(f, "{inner} FILTER({expr})")
718 }
719 Self::Union { left, right } => write!(f, "{{ {left} }} UNION {{ {right} }}"),
720 Self::Graph { name, inner } => {
721 write!(f, "GRAPH {name} {{ {inner} }}")
722 }
723 Self::Extend {
724 inner,
725 variable,
726 expression,
727 } => write!(f, "{inner} BIND({expression} AS {variable})"),
728 Self::Minus { left, right } => write!(f, "{left} MINUS {{ {right} }}"),
729 Self::Service {
730 name,
731 inner,
732 silent,
733 } => {
734 if *silent {
735 write!(f, "SERVICE SILENT {name} {{ {inner} }}")
736 } else {
737 write!(f, "SERVICE {name} {{ {inner} }}")
738 }
739 }
740 Self::Values {
741 variables,
742 bindings,
743 } => {
744 f.write_str("VALUES ( ")?;
745 for var in variables {
746 write!(f, "{var} ")?;
747 }
748 f.write_str(") { ")?;
749 for row in bindings {
750 f.write_str("( ")?;
751 for val in row {
752 match val {
753 Some(val) => write!(f, "{val} "),
754 None => f.write_str("UNDEF "),
755 }?;
756 }
757 f.write_str(") ")?;
758 }
759 f.write_str(" }")
760 }
761 Self::Group {
762 inner,
763 variables,
764 aggregates,
765 } => {
766 f.write_str("{SELECT")?;
767 for (a, v) in aggregates {
768 write!(f, " ({v} AS {a})")?;
769 }
770 for b in variables {
771 write!(f, " {b}")?;
772 }
773 write!(f, " WHERE {{ {inner} }}")?;
774 if !variables.is_empty() {
775 f.write_str(" GROUP BY")?;
776 for v in variables {
777 write!(f, " {v}")?;
778 }
779 }
780 f.write_str("}")
781 }
782 p => write!(
783 f,
784 "{{ {} }}",
785 SparqlGraphRootPattern {
786 pattern: p,
787 dataset: None
788 }
789 ),
790 }
791 }
792}
793
794impl Default for GraphPattern {
795 fn default() -> Self {
796 Self::Bgp {
797 patterns: Vec::new(),
798 }
799 }
800}
801
802impl GraphPattern {
803 pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
805 match self {
806 Self::Bgp { patterns } => {
807 f.write_str("(bgp")?;
808 for pattern in patterns {
809 f.write_str(" ")?;
810 pattern.fmt_sse(f)?;
811 }
812 f.write_str(")")
813 }
814 Self::Path {
815 subject,
816 path,
817 object,
818 } => {
819 f.write_str("(path ")?;
820 subject.fmt_sse(f)?;
821 f.write_str(" ")?;
822 path.fmt_sse(f)?;
823 f.write_str(" ")?;
824 object.fmt_sse(f)?;
825 f.write_str(")")
826 }
827 Self::Join { left, right } => {
828 f.write_str("(join ")?;
829 left.fmt_sse(f)?;
830 f.write_str(" ")?;
831 right.fmt_sse(f)?;
832 f.write_str(")")
833 }
834 Self::LeftJoin {
835 left,
836 right,
837 expression,
838 } => {
839 f.write_str("(leftjoin ")?;
840 left.fmt_sse(f)?;
841 f.write_str(" ")?;
842 right.fmt_sse(f)?;
843 if let Some(expr) = expression {
844 f.write_str(" ")?;
845 expr.fmt_sse(f)?;
846 }
847 f.write_str(")")
848 }
849 #[cfg(feature = "sep-0006")]
850 Self::Lateral { left, right } => {
851 f.write_str("(lateral ")?;
852 left.fmt_sse(f)?;
853 f.write_str(" ")?;
854 right.fmt_sse(f)?;
855 f.write_str(")")
856 }
857 Self::Filter { expr, inner } => {
858 f.write_str("(filter ")?;
859 expr.fmt_sse(f)?;
860 f.write_str(" ")?;
861 inner.fmt_sse(f)?;
862 f.write_str(")")
863 }
864 Self::Union { left, right } => {
865 f.write_str("(union ")?;
866 left.fmt_sse(f)?;
867 f.write_str(" ")?;
868 right.fmt_sse(f)?;
869 f.write_str(")")
870 }
871 Self::Graph { name, inner } => {
872 f.write_str("(graph ")?;
873 name.fmt_sse(f)?;
874 f.write_str(" ")?;
875 inner.fmt_sse(f)?;
876 f.write_str(")")
877 }
878 Self::Extend {
879 inner,
880 variable,
881 expression,
882 } => {
883 write!(f, "(extend (({variable} ")?;
884 expression.fmt_sse(f)?;
885 f.write_str(")) ")?;
886 inner.fmt_sse(f)?;
887 f.write_str(")")
888 }
889 Self::Minus { left, right } => {
890 f.write_str("(minus ")?;
891 left.fmt_sse(f)?;
892 f.write_str(" ")?;
893 right.fmt_sse(f)?;
894 f.write_str(")")
895 }
896 Self::Service {
897 name,
898 inner,
899 silent,
900 } => {
901 f.write_str("(service ")?;
902 if *silent {
903 f.write_str("silent ")?;
904 }
905 name.fmt_sse(f)?;
906 f.write_str(" ")?;
907 inner.fmt_sse(f)?;
908 f.write_str(")")
909 }
910 Self::Group {
911 inner,
912 variables,
913 aggregates,
914 } => {
915 f.write_str("(group (")?;
916 for (i, v) in variables.iter().enumerate() {
917 if i > 0 {
918 f.write_str(" ")?;
919 }
920 write!(f, "{v}")?;
921 }
922 f.write_str(") (")?;
923 for (i, (v, a)) in aggregates.iter().enumerate() {
924 if i > 0 {
925 f.write_str(" ")?;
926 }
927 f.write_str("(")?;
928 a.fmt_sse(f)?;
929 write!(f, " {v})")?;
930 }
931 f.write_str(") ")?;
932 inner.fmt_sse(f)?;
933 f.write_str(")")
934 }
935 Self::Values {
936 variables,
937 bindings,
938 } => {
939 f.write_str("(table (vars")?;
940 for var in variables {
941 write!(f, " {var}")?;
942 }
943 f.write_str(")")?;
944 for row in bindings {
945 f.write_str(" (row")?;
946 for (value, var) in row.iter().zip(variables) {
947 if let Some(value) = value {
948 write!(f, " ({var} {value})")?;
949 }
950 }
951 f.write_str(")")?;
952 }
953 f.write_str(")")
954 }
955 Self::OrderBy { inner, expression } => {
956 f.write_str("(order (")?;
957 for (i, c) in expression.iter().enumerate() {
958 if i > 0 {
959 f.write_str(" ")?;
960 }
961 c.fmt_sse(f)?;
962 }
963 f.write_str(") ")?;
964 inner.fmt_sse(f)?;
965 f.write_str(")")
966 }
967 Self::Project { inner, variables } => {
968 f.write_str("(project (")?;
969 for (i, v) in variables.iter().enumerate() {
970 if i > 0 {
971 f.write_str(" ")?;
972 }
973 write!(f, "{v}")?;
974 }
975 f.write_str(") ")?;
976 inner.fmt_sse(f)?;
977 f.write_str(")")
978 }
979 Self::Distinct { inner } => {
980 f.write_str("(distinct ")?;
981 inner.fmt_sse(f)?;
982 f.write_str(")")
983 }
984 Self::Reduced { inner } => {
985 f.write_str("(reduced ")?;
986 inner.fmt_sse(f)?;
987 f.write_str(")")
988 }
989 Self::Slice {
990 inner,
991 start,
992 length,
993 } => {
994 if let Some(length) = length {
995 write!(f, "(slice {start} {length} ")?;
996 } else {
997 write!(f, "(slice {start} _ ")?;
998 }
999 inner.fmt_sse(f)?;
1000 f.write_str(")")
1001 }
1002 }
1003 }
1004
1005 pub fn on_in_scope_variable<'a>(&'a self, mut callback: impl FnMut(&'a Variable)) {
1007 self.lookup_in_scope_variables(&mut callback)
1008 }
1009
1010 fn lookup_in_scope_variables<'a>(&'a self, callback: &mut impl FnMut(&'a Variable)) {
1011 match self {
1012 Self::Bgp { patterns } => {
1013 for pattern in patterns {
1014 lookup_triple_pattern_variables(pattern, callback)
1015 }
1016 }
1017 Self::Path {
1018 subject, object, ..
1019 } => {
1020 if let TermPattern::Variable(s) = subject {
1021 callback(s);
1022 }
1023 #[cfg(feature = "sparql-12")]
1024 if let TermPattern::Triple(s) = subject {
1025 lookup_triple_pattern_variables(s, callback)
1026 }
1027 if let TermPattern::Variable(o) = object {
1028 callback(o);
1029 }
1030 #[cfg(feature = "sparql-12")]
1031 if let TermPattern::Triple(o) = object {
1032 lookup_triple_pattern_variables(o, callback)
1033 }
1034 }
1035 Self::Join { left, right }
1036 | Self::LeftJoin { left, right, .. }
1037 | Self::Union { left, right } => {
1038 left.lookup_in_scope_variables(callback);
1039 right.lookup_in_scope_variables(callback);
1040 }
1041 #[cfg(feature = "sep-0006")]
1042 Self::Lateral { left, right } => {
1043 left.lookup_in_scope_variables(callback);
1044 right.lookup_in_scope_variables(callback);
1045 }
1046 Self::Graph { name, inner } => {
1047 if let NamedNodePattern::Variable(g) = &name {
1048 callback(g);
1049 }
1050 inner.lookup_in_scope_variables(callback);
1051 }
1052 Self::Extend {
1053 inner, variable, ..
1054 } => {
1055 callback(variable);
1056 inner.lookup_in_scope_variables(callback);
1057 }
1058 Self::Minus { left, .. } => left.lookup_in_scope_variables(callback),
1059 Self::Group {
1060 variables,
1061 aggregates,
1062 ..
1063 } => {
1064 for v in variables {
1065 callback(v);
1066 }
1067 for (v, _) in aggregates {
1068 callback(v);
1069 }
1070 }
1071 Self::Values { variables, .. } | Self::Project { variables, .. } => {
1072 for v in variables {
1073 callback(v);
1074 }
1075 }
1076 Self::Service { inner, .. }
1077 | Self::Filter { inner, .. }
1078 | Self::OrderBy { inner, .. }
1079 | Self::Distinct { inner }
1080 | Self::Reduced { inner }
1081 | Self::Slice { inner, .. } => inner.lookup_in_scope_variables(callback),
1082 }
1083 }
1084
1085 fn lookup_used_variables<'a>(&'a self, callback: &mut impl FnMut(&'a Variable)) {
1086 match self {
1087 Self::Bgp { patterns } => {
1088 for pattern in patterns {
1089 lookup_triple_pattern_variables(pattern, callback)
1090 }
1091 }
1092 Self::Path {
1093 subject, object, ..
1094 } => {
1095 if let TermPattern::Variable(s) = subject {
1096 callback(s);
1097 }
1098 #[cfg(feature = "sparql-12")]
1099 if let TermPattern::Triple(s) = subject {
1100 lookup_triple_pattern_variables(s, callback)
1101 }
1102 if let TermPattern::Variable(o) = object {
1103 callback(o);
1104 }
1105 #[cfg(feature = "sparql-12")]
1106 if let TermPattern::Triple(o) = object {
1107 lookup_triple_pattern_variables(o, callback)
1108 }
1109 }
1110 Self::Join { left, right }
1111 | Self::Minus { left, right }
1112 | Self::Union { left, right } => {
1113 left.lookup_used_variables(callback);
1114 right.lookup_used_variables(callback);
1115 }
1116 Self::LeftJoin {
1117 left,
1118 right,
1119 expression,
1120 } => {
1121 left.lookup_used_variables(callback);
1122 right.lookup_used_variables(callback);
1123 if let Some(expr) = expression {
1124 expr.lookup_used_variable(callback);
1125 }
1126 }
1127 #[cfg(feature = "sep-0006")]
1128 Self::Lateral { left, right } => {
1129 left.lookup_used_variables(callback);
1130 right.lookup_used_variables(callback);
1131 }
1132 Self::Graph { name, inner } => {
1133 if let NamedNodePattern::Variable(g) = &name {
1134 callback(g);
1135 }
1136 inner.lookup_used_variables(callback);
1137 }
1138 Self::Extend {
1139 inner,
1140 variable,
1141 expression,
1142 } => {
1143 callback(variable);
1144 expression.lookup_used_variable(callback);
1145 inner.lookup_used_variables(callback);
1146 }
1147 Self::Group {
1148 inner,
1149 variables,
1150 aggregates,
1151 } => {
1152 inner.lookup_used_variables(callback);
1153 for v in variables {
1154 callback(v);
1155 }
1156 for (v, expr) in aggregates {
1157 callback(v);
1158 expr.lookup_used_variables(callback);
1159 }
1160 }
1161 Self::Values { variables, .. } | Self::Project { variables, .. } => {
1162 for v in variables {
1163 callback(v);
1164 }
1165 }
1166 Self::Filter { inner, expr } => {
1167 expr.lookup_used_variable(callback);
1168 inner.lookup_used_variables(callback);
1169 }
1170 Self::Service { inner, name, .. } => {
1171 if let NamedNodePattern::Variable(s) = &name {
1172 callback(s);
1173 }
1174 inner.lookup_used_variables(callback);
1175 }
1176 Self::OrderBy { inner, expression } => {
1177 for e in expression {
1178 e.lookup_used_variables(callback);
1179 }
1180 inner.lookup_used_variables(callback);
1181 }
1182 Self::Distinct { inner } | Self::Reduced { inner } | Self::Slice { inner, .. } => {
1183 inner.lookup_used_variables(callback)
1184 }
1185 }
1186 }
1187}
1188
1189fn lookup_triple_pattern_variables<'a>(
1190 pattern: &'a TriplePattern,
1191 callback: &mut impl FnMut(&'a Variable),
1192) {
1193 if let TermPattern::Variable(s) = &pattern.subject {
1194 callback(s);
1195 }
1196 #[cfg(feature = "sparql-12")]
1197 if let TermPattern::Triple(s) = &pattern.subject {
1198 lookup_triple_pattern_variables(s, callback)
1199 }
1200 if let NamedNodePattern::Variable(p) = &pattern.predicate {
1201 callback(p);
1202 }
1203 if let TermPattern::Variable(o) = &pattern.object {
1204 callback(o);
1205 }
1206 #[cfg(feature = "sparql-12")]
1207 if let TermPattern::Triple(o) = &pattern.object {
1208 lookup_triple_pattern_variables(o, callback)
1209 }
1210}
1211
1212pub(crate) struct SparqlGraphRootPattern<'a> {
1213 pattern: &'a GraphPattern,
1214 dataset: Option<&'a QueryDataset>,
1215}
1216
1217impl<'a> SparqlGraphRootPattern<'a> {
1218 pub fn new(pattern: &'a GraphPattern, dataset: Option<&'a QueryDataset>) -> Self {
1219 Self { pattern, dataset }
1220 }
1221}
1222
1223impl fmt::Display for SparqlGraphRootPattern<'_> {
1224 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1225 let mut distinct = false;
1226 let mut reduced = false;
1227 let mut order = None;
1228 let mut start = 0;
1229 let mut length = None;
1230 let mut project = Vec::new();
1231
1232 let mut child = self.pattern;
1233 loop {
1234 match child {
1235 GraphPattern::OrderBy { inner, expression } => {
1236 order = Some(expression);
1237 child = inner;
1238 }
1239 GraphPattern::Project { inner, variables } if project.is_empty() => {
1240 project.extend(variables.iter().map(|v| (v, None)));
1241 child = inner;
1242 }
1243 GraphPattern::Distinct { inner } => {
1244 distinct = true;
1245 child = inner;
1246 }
1247 GraphPattern::Reduced { inner } => {
1248 reduced = true;
1249 child = inner;
1250 }
1251 GraphPattern::Slice {
1252 inner,
1253 start: s,
1254 length: l,
1255 } => {
1256 start = *s;
1257 length = *l;
1258 child = inner;
1259 }
1260 GraphPattern::Extend {
1261 inner,
1262 expression,
1263 variable,
1264 } if project.iter().any(|(v, _)| *v == variable)
1265 && !project.iter().any(|(_, expr)| {
1266 expr.is_some_and(|expr: &Expression| {
1267 let mut found = false;
1268 expr.lookup_used_variable(&mut |v| found |= v == variable);
1269 found
1270 })
1271 }) =>
1272 {
1273 project
1275 .iter_mut()
1276 .find(|(v, _)| *v == variable)
1277 .ok_or(fmt::Error)?
1278 .1 = Some(expression);
1279 child = inner
1280 }
1281 p => {
1282 f.write_str("SELECT")?;
1283 if distinct {
1284 f.write_str(" DISTINCT")?;
1285 }
1286 if reduced {
1287 f.write_str(" REDUCED")?;
1288 }
1289 if project.is_empty() {
1290 f.write_str(" *")?;
1291 } else {
1292 for (variable, expr) in project {
1293 if let Some(expr) = expr {
1294 write!(f, " ({expr} AS {variable})")
1295 } else {
1296 write!(f, " {variable}")
1297 }?;
1298 }
1299 }
1300 if let Some(dataset) = self.dataset {
1301 write!(f, " {dataset}")?;
1302 }
1303 write!(f, " WHERE {{ {p} }}")?;
1304 if let Some(order) = order {
1305 f.write_str(" ORDER BY")?;
1306 for c in order {
1307 write!(f, " {c}")?;
1308 }
1309 }
1310 if start > 0 {
1311 write!(f, " OFFSET {start}")?;
1312 }
1313 if let Some(length) = length {
1314 write!(f, " LIMIT {length}")?;
1315 }
1316 return Ok(());
1317 }
1318 }
1319 }
1320 }
1321}
1322
1323#[derive(Eq, PartialEq, Debug, Clone, Hash)]
1325pub enum AggregateExpression {
1326 CountSolutions { distinct: bool },
1328 FunctionCall {
1329 name: AggregateFunction,
1330 expr: Expression,
1331 distinct: bool,
1332 },
1333}
1334
1335impl AggregateExpression {
1336 pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
1338 match self {
1339 Self::CountSolutions { distinct } => {
1340 f.write_str("(count")?;
1341 if *distinct {
1342 f.write_str(" distinct")?;
1343 }
1344 f.write_str(")")
1345 }
1346 Self::FunctionCall {
1347 name:
1348 AggregateFunction::GroupConcat {
1349 separator: Some(separator),
1350 },
1351 expr,
1352 distinct,
1353 } => {
1354 f.write_str("(group_concat ")?;
1355 if *distinct {
1356 f.write_str("distinct ")?;
1357 }
1358 expr.fmt_sse(f)?;
1359 write!(f, " {})", LiteralRef::new_simple_literal(separator))
1360 }
1361 Self::FunctionCall {
1362 name,
1363 expr,
1364 distinct,
1365 } => {
1366 f.write_str("(")?;
1367 name.fmt_sse(f)?;
1368 f.write_str(" ")?;
1369 if *distinct {
1370 f.write_str("distinct ")?;
1371 }
1372 expr.fmt_sse(f)?;
1373 f.write_str(")")
1374 }
1375 }
1376 }
1377
1378 fn lookup_used_variables<'a>(&'a self, callback: &mut impl FnMut(&'a Variable)) {
1379 if let Self::FunctionCall { expr, .. } = self {
1380 expr.lookup_used_variable(callback);
1381 }
1382 }
1383}
1384
1385impl fmt::Display for AggregateExpression {
1386 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1387 match self {
1388 Self::CountSolutions { distinct } => {
1389 if *distinct {
1390 f.write_str("COUNT(DISTINCT *)")
1391 } else {
1392 f.write_str("COUNT(*)")
1393 }
1394 }
1395 Self::FunctionCall {
1396 name:
1397 AggregateFunction::GroupConcat {
1398 separator: Some(separator),
1399 },
1400 expr,
1401 distinct,
1402 } => {
1403 if *distinct {
1404 write!(
1405 f,
1406 "GROUP_CONCAT(DISTINCT {}; SEPARATOR = {})",
1407 expr,
1408 LiteralRef::new_simple_literal(separator)
1409 )
1410 } else {
1411 write!(
1412 f,
1413 "GROUP_CONCAT({}; SEPARATOR = {})",
1414 expr,
1415 LiteralRef::new_simple_literal(separator)
1416 )
1417 }
1418 }
1419 Self::FunctionCall {
1420 name,
1421 expr,
1422 distinct,
1423 } => {
1424 if *distinct {
1425 write!(f, "{name}(DISTINCT {expr})")
1426 } else {
1427 write!(f, "{name}({expr})")
1428 }
1429 }
1430 }
1431 }
1432}
1433
1434#[derive(Eq, PartialEq, Debug, Clone, Hash)]
1436pub enum AggregateFunction {
1437 Count,
1439 Sum,
1441 Avg,
1443 Min,
1445 Max,
1447 GroupConcat {
1449 separator: Option<String>,
1450 },
1451 Sample,
1453 Custom(NamedNode),
1454}
1455
1456impl AggregateFunction {
1457 pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
1459 match self {
1460 Self::Count => f.write_str("count"),
1461 Self::Sum => f.write_str("sum"),
1462 Self::Avg => f.write_str("avg"),
1463 Self::Min => f.write_str("min"),
1464 Self::Max => f.write_str("max"),
1465 Self::GroupConcat { .. } => f.write_str("group_concat"),
1466 Self::Sample => f.write_str("sample"),
1467 Self::Custom(iri) => write!(f, "{iri}"),
1468 }
1469 }
1470}
1471
1472impl fmt::Display for AggregateFunction {
1473 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1474 match self {
1475 Self::Count => f.write_str("COUNT"),
1476 Self::Sum => f.write_str("SUM"),
1477 Self::Avg => f.write_str("AVG"),
1478 Self::Min => f.write_str("MIN"),
1479 Self::Max => f.write_str("MAX"),
1480 Self::GroupConcat { .. } => f.write_str("GROUP_CONCAT"),
1481 Self::Sample => f.write_str("SAMPLE"),
1482 Self::Custom(iri) => iri.fmt(f),
1483 }
1484 }
1485}
1486
1487#[derive(Eq, PartialEq, Debug, Clone, Hash)]
1489pub enum OrderExpression {
1490 Asc(Expression),
1492 Desc(Expression),
1494}
1495
1496impl OrderExpression {
1497 pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
1499 match self {
1500 Self::Asc(e) => {
1501 f.write_str("(asc ")?;
1502 e.fmt_sse(f)?;
1503 f.write_str(")")
1504 }
1505 Self::Desc(e) => {
1506 f.write_str("(desc ")?;
1507 e.fmt_sse(f)?;
1508 f.write_str(")")
1509 }
1510 }
1511 }
1512
1513 fn lookup_used_variables<'a>(&'a self, callback: &mut impl FnMut(&'a Variable)) {
1514 let (Self::Asc(e) | Self::Desc(e)) = self;
1515 e.lookup_used_variable(callback);
1516 }
1517}
1518
1519impl fmt::Display for OrderExpression {
1520 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1521 match self {
1522 Self::Asc(e) => write!(f, "ASC({e})"),
1523 Self::Desc(e) => write!(f, "DESC({e})"),
1524 }
1525 }
1526}
1527
1528#[derive(Eq, PartialEq, Debug, Clone, Hash)]
1530pub struct QueryDataset {
1531 pub default: Vec<NamedNode>,
1532 pub named: Option<Vec<NamedNode>>,
1533}
1534
1535impl QueryDataset {
1536 pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
1538 f.write_str("(")?;
1539 for (i, graph_name) in self.default.iter().enumerate() {
1540 if i > 0 {
1541 f.write_str(" ")?;
1542 }
1543 write!(f, "{graph_name}")?;
1544 }
1545 if let Some(named) = &self.named {
1546 for (i, graph_name) in named.iter().enumerate() {
1547 if !self.default.is_empty() || i > 0 {
1548 f.write_str(" ")?;
1549 }
1550 write!(f, "(named {graph_name})")?;
1551 }
1552 }
1553 f.write_str(")")
1554 }
1555}
1556
1557impl fmt::Display for QueryDataset {
1558 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1559 for g in &self.default {
1560 write!(f, " FROM {g}")?;
1561 }
1562 if let Some(named) = &self.named {
1563 for g in named {
1564 write!(f, " FROM NAMED {g}")?;
1565 }
1566 }
1567 Ok(())
1568 }
1569}
1570
1571#[derive(Eq, PartialEq, Debug, Clone, Hash)]
1575pub enum GraphTarget {
1576 NamedNode(NamedNode),
1577 DefaultGraph,
1578 NamedGraphs,
1579 AllGraphs,
1580}
1581
1582impl GraphTarget {
1583 pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
1585 match self {
1586 Self::NamedNode(node) => write!(f, "{node}"),
1587 Self::DefaultGraph => f.write_str("default"),
1588 Self::NamedGraphs => f.write_str("named"),
1589 Self::AllGraphs => f.write_str("all"),
1590 }
1591 }
1592}
1593
1594impl fmt::Display for GraphTarget {
1595 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1596 match self {
1597 Self::NamedNode(node) => write!(f, "GRAPH {node}"),
1598 Self::DefaultGraph => f.write_str("DEFAULT"),
1599 Self::NamedGraphs => f.write_str("NAMED"),
1600 Self::AllGraphs => f.write_str("ALL"),
1601 }
1602 }
1603}
1604
1605impl From<NamedNode> for GraphTarget {
1606 fn from(node: NamedNode) -> Self {
1607 Self::NamedNode(node)
1608 }
1609}
1610
1611impl From<GraphName> for GraphTarget {
1612 fn from(graph_name: GraphName) -> Self {
1613 match graph_name {
1614 GraphName::NamedNode(node) => Self::NamedNode(node),
1615 GraphName::DefaultGraph => Self::DefaultGraph,
1616 }
1617 }
1618}
1619
1620#[inline]
1621fn fmt_sse_unary_expression(f: &mut impl fmt::Write, name: &str, e: &Expression) -> fmt::Result {
1622 write!(f, "({name} ")?;
1623 e.fmt_sse(f)?;
1624 f.write_str(")")
1625}
1626
1627#[inline]
1628fn fmt_sse_binary_expression(
1629 f: &mut impl fmt::Write,
1630 name: &str,
1631 a: &Expression,
1632 b: &Expression,
1633) -> fmt::Result {
1634 write!(f, "({name} ")?;
1635 a.fmt_sse(f)?;
1636 f.write_str(" ")?;
1637 b.fmt_sse(f)?;
1638 f.write_str(")")
1639}