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
217impl fmt::Display for Expression {
218 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
219 match self {
220 Self::NamedNode(node) => node.fmt(f),
221 Self::Literal(l) => l.fmt(f),
222 Self::Variable(var) => var.fmt(f),
223 Self::Or(a, b) => write!(f, "({a} || {b})"),
224 Self::And(a, b) => write!(f, "({a} && {b})"),
225 Self::Equal(a, b) => {
226 write!(f, "({a} = {b})")
227 }
228 Self::SameTerm(a, b) => {
229 write!(f, "sameTerm({a}, {b})")
230 }
231 Self::Greater(a, b) => {
232 write!(f, "({a} > {b})")
233 }
234 Self::GreaterOrEqual(a, b) => write!(f, "({a} >= {b})"),
235 Self::Less(a, b) => {
236 write!(f, "({a} < {b})")
237 }
238 Self::LessOrEqual(a, b) => write!(f, "({a} <= {b})"),
239 Self::In(a, b) => {
240 write!(f, "({a} IN ")?;
241 write_arg_list(b, f)?;
242 f.write_str(")")
243 }
244 Self::Add(a, b) => {
245 write!(f, "{a} + {b}")
246 }
247 Self::Subtract(a, b) => {
248 write!(f, "{a} - {b}")
249 }
250 Self::Multiply(a, b) => {
251 write!(f, "{a} * {b}")
252 }
253 Self::Divide(a, b) => {
254 write!(f, "{a} / {b}")
255 }
256 Self::UnaryPlus(e) => write!(f, "+{e}"),
257 Self::UnaryMinus(e) => write!(f, "-{e}"),
258 Self::Not(e) => match e.as_ref() {
259 Self::Exists(p) => write!(f, "NOT EXISTS {{ {p} }}"),
260 e => write!(f, "!{e}"),
261 },
262 Self::FunctionCall(function, parameters) => {
263 write!(f, "{function}")?;
264 write_arg_list(parameters, f)
265 }
266 Self::Bound(v) => write!(f, "BOUND({v})"),
267 Self::Exists(p) => write!(f, "EXISTS {{ {p} }}"),
268 Self::If(a, b, c) => write!(f, "IF({a}, {b}, {c})"),
269 Self::Coalesce(parameters) => {
270 f.write_str("COALESCE")?;
271 write_arg_list(parameters, f)
272 }
273 }
274 }
275}
276
277impl From<NamedNode> for Expression {
278 fn from(p: NamedNode) -> Self {
279 Self::NamedNode(p)
280 }
281}
282
283impl From<Literal> for Expression {
284 fn from(p: Literal) -> Self {
285 Self::Literal(p)
286 }
287}
288
289impl From<Variable> for Expression {
290 fn from(v: Variable) -> Self {
291 Self::Variable(v)
292 }
293}
294
295impl From<NamedNodePattern> for Expression {
296 fn from(p: NamedNodePattern) -> Self {
297 match p {
298 NamedNodePattern::NamedNode(p) => p.into(),
299 NamedNodePattern::Variable(p) => p.into(),
300 }
301 }
302}
303
304fn write_arg_list(
305 params: impl IntoIterator<Item = impl fmt::Display>,
306 f: &mut fmt::Formatter<'_>,
307) -> fmt::Result {
308 f.write_str("(")?;
309 let mut cont = false;
310 for p in params {
311 if cont {
312 f.write_str(", ")?;
313 }
314 p.fmt(f)?;
315 cont = true;
316 }
317 f.write_str(")")
318}
319
320#[derive(Eq, PartialEq, Debug, Clone, Hash)]
322pub enum Function {
323 Str,
324 Lang,
325 LangMatches,
326 Datatype,
327 Iri,
328 BNode,
329 Rand,
330 Abs,
331 Ceil,
332 Floor,
333 Round,
334 Concat,
335 SubStr,
336 StrLen,
337 Replace,
338 UCase,
339 LCase,
340 EncodeForUri,
341 Contains,
342 StrStarts,
343 StrEnds,
344 StrBefore,
345 StrAfter,
346 Year,
347 Month,
348 Day,
349 Hours,
350 Minutes,
351 Seconds,
352 Timezone,
353 Tz,
354 Now,
355 Uuid,
356 StrUuid,
357 Md5,
358 Sha1,
359 Sha256,
360 Sha384,
361 Sha512,
362 StrLang,
363 StrDt,
364 IsIri,
365 IsBlank,
366 IsLiteral,
367 IsNumeric,
368 Regex,
369 #[cfg(feature = "rdf-star")]
370 Triple,
371 #[cfg(feature = "rdf-star")]
372 Subject,
373 #[cfg(feature = "rdf-star")]
374 Predicate,
375 #[cfg(feature = "rdf-star")]
376 Object,
377 #[cfg(feature = "rdf-star")]
378 IsTriple,
379 #[cfg(feature = "sep-0002")]
380 Adjust,
381 Custom(NamedNode),
382}
383
384impl Function {
385 pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
387 match self {
388 Self::Str => f.write_str("str"),
389 Self::Lang => f.write_str("lang"),
390 Self::LangMatches => f.write_str("langmatches"),
391 Self::Datatype => f.write_str("datatype"),
392 Self::Iri => f.write_str("iri"),
393 Self::BNode => f.write_str("bnode"),
394 Self::Rand => f.write_str("rand"),
395 Self::Abs => f.write_str("abs"),
396 Self::Ceil => f.write_str("ceil"),
397 Self::Floor => f.write_str("floor"),
398 Self::Round => f.write_str("round"),
399 Self::Concat => f.write_str("concat"),
400 Self::SubStr => f.write_str("substr"),
401 Self::StrLen => f.write_str("strlen"),
402 Self::Replace => f.write_str("replace"),
403 Self::UCase => f.write_str("ucase"),
404 Self::LCase => f.write_str("lcase"),
405 Self::EncodeForUri => f.write_str("encode_for_uri"),
406 Self::Contains => f.write_str("contains"),
407 Self::StrStarts => f.write_str("strstarts"),
408 Self::StrEnds => f.write_str("strends"),
409 Self::StrBefore => f.write_str("strbefore"),
410 Self::StrAfter => f.write_str("strafter"),
411 Self::Year => f.write_str("year"),
412 Self::Month => f.write_str("month"),
413 Self::Day => f.write_str("day"),
414 Self::Hours => f.write_str("hours"),
415 Self::Minutes => f.write_str("minutes"),
416 Self::Seconds => f.write_str("seconds"),
417 Self::Timezone => f.write_str("timezone"),
418 Self::Tz => f.write_str("tz"),
419 Self::Now => f.write_str("now"),
420 Self::Uuid => f.write_str("uuid"),
421 Self::StrUuid => f.write_str("struuid"),
422 Self::Md5 => f.write_str("md5"),
423 Self::Sha1 => f.write_str("sha1"),
424 Self::Sha256 => f.write_str("sha256"),
425 Self::Sha384 => f.write_str("sha384"),
426 Self::Sha512 => f.write_str("sha512"),
427 Self::StrLang => f.write_str("strlang"),
428 Self::StrDt => f.write_str("strdt"),
429 Self::IsIri => f.write_str("isiri"),
430 Self::IsBlank => f.write_str("isblank"),
431 Self::IsLiteral => f.write_str("isliteral"),
432 Self::IsNumeric => f.write_str("isnumeric"),
433 Self::Regex => f.write_str("regex"),
434 #[cfg(feature = "rdf-star")]
435 Self::Triple => f.write_str("triple"),
436 #[cfg(feature = "rdf-star")]
437 Self::Subject => f.write_str("subject"),
438 #[cfg(feature = "rdf-star")]
439 Self::Predicate => f.write_str("predicate"),
440 #[cfg(feature = "rdf-star")]
441 Self::Object => f.write_str("object"),
442 #[cfg(feature = "rdf-star")]
443 Self::IsTriple => f.write_str("istriple"),
444 #[cfg(feature = "sep-0002")]
445 Self::Adjust => f.write_str("adjust"),
446 Self::Custom(iri) => write!(f, "{iri}"),
447 }
448 }
449}
450
451impl fmt::Display for Function {
452 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
453 match self {
454 Self::Str => f.write_str("STR"),
455 Self::Lang => f.write_str("LANG"),
456 Self::LangMatches => f.write_str("LANGMATCHES"),
457 Self::Datatype => f.write_str("DATATYPE"),
458 Self::Iri => f.write_str("IRI"),
459 Self::BNode => f.write_str("BNODE"),
460 Self::Rand => f.write_str("RAND"),
461 Self::Abs => f.write_str("ABS"),
462 Self::Ceil => f.write_str("CEIL"),
463 Self::Floor => f.write_str("FLOOR"),
464 Self::Round => f.write_str("ROUND"),
465 Self::Concat => f.write_str("CONCAT"),
466 Self::SubStr => f.write_str("SUBSTR"),
467 Self::StrLen => f.write_str("STRLEN"),
468 Self::Replace => f.write_str("REPLACE"),
469 Self::UCase => f.write_str("UCASE"),
470 Self::LCase => f.write_str("LCASE"),
471 Self::EncodeForUri => f.write_str("ENCODE_FOR_URI"),
472 Self::Contains => f.write_str("CONTAINS"),
473 Self::StrStarts => f.write_str("STRSTARTS"),
474 Self::StrEnds => f.write_str("STRENDS"),
475 Self::StrBefore => f.write_str("STRBEFORE"),
476 Self::StrAfter => f.write_str("STRAFTER"),
477 Self::Year => f.write_str("YEAR"),
478 Self::Month => f.write_str("MONTH"),
479 Self::Day => f.write_str("DAY"),
480 Self::Hours => f.write_str("HOURS"),
481 Self::Minutes => f.write_str("MINUTES"),
482 Self::Seconds => f.write_str("SECONDS"),
483 Self::Timezone => f.write_str("TIMEZONE"),
484 Self::Tz => f.write_str("TZ"),
485 Self::Now => f.write_str("NOW"),
486 Self::Uuid => f.write_str("UUID"),
487 Self::StrUuid => f.write_str("STRUUID"),
488 Self::Md5 => f.write_str("MD5"),
489 Self::Sha1 => f.write_str("SHA1"),
490 Self::Sha256 => f.write_str("SHA256"),
491 Self::Sha384 => f.write_str("SHA384"),
492 Self::Sha512 => f.write_str("SHA512"),
493 Self::StrLang => f.write_str("STRLANG"),
494 Self::StrDt => f.write_str("STRDT"),
495 Self::IsIri => f.write_str("isIRI"),
496 Self::IsBlank => f.write_str("isBLANK"),
497 Self::IsLiteral => f.write_str("isLITERAL"),
498 Self::IsNumeric => f.write_str("isNUMERIC"),
499 Self::Regex => f.write_str("REGEX"),
500 #[cfg(feature = "rdf-star")]
501 Self::Triple => f.write_str("TRIPLE"),
502 #[cfg(feature = "rdf-star")]
503 Self::Subject => f.write_str("SUBJECT"),
504 #[cfg(feature = "rdf-star")]
505 Self::Predicate => f.write_str("PREDICATE"),
506 #[cfg(feature = "rdf-star")]
507 Self::Object => f.write_str("OBJECT"),
508 #[cfg(feature = "rdf-star")]
509 Self::IsTriple => f.write_str("isTRIPLE"),
510 #[cfg(feature = "sep-0002")]
511 Self::Adjust => f.write_str("ADJUST"),
512 Self::Custom(iri) => iri.fmt(f),
513 }
514 }
515}
516
517#[derive(Eq, PartialEq, Debug, Clone, Hash)]
519pub enum GraphPattern {
520 Bgp { patterns: Vec<TriplePattern> },
522 Path {
524 subject: TermPattern,
525 path: PropertyPathExpression,
526 object: TermPattern,
527 },
528 Join { left: Box<Self>, right: Box<Self> },
530 LeftJoin {
532 left: Box<Self>,
533 right: Box<Self>,
534 expression: Option<Expression>,
535 },
536 #[cfg(feature = "sep-0006")]
538 Lateral { left: Box<Self>, right: Box<Self> },
539 Filter { expr: Expression, inner: Box<Self> },
541 Union { left: Box<Self>, right: Box<Self> },
543 Graph {
544 name: NamedNodePattern,
545 inner: Box<Self>,
546 },
547 Extend {
549 inner: Box<Self>,
550 variable: Variable,
551 expression: Expression,
552 },
553 Minus { left: Box<Self>, right: Box<Self> },
555 Values {
557 variables: Vec<Variable>,
558 bindings: Vec<Vec<Option<GroundTerm>>>,
559 },
560 OrderBy {
562 inner: Box<Self>,
563 expression: Vec<OrderExpression>,
564 },
565 Project {
567 inner: Box<Self>,
568 variables: Vec<Variable>,
569 },
570 Distinct { inner: Box<Self> },
572 Reduced { inner: Box<Self> },
574 Slice {
576 inner: Box<Self>,
577 start: usize,
578 length: Option<usize>,
579 },
580 Group {
582 inner: Box<Self>,
583 variables: Vec<Variable>,
584 aggregates: Vec<(Variable, AggregateExpression)>,
585 },
586 Service {
588 name: NamedNodePattern,
589 inner: Box<Self>,
590 silent: bool,
591 },
592}
593
594impl fmt::Display for GraphPattern {
595 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
596 match self {
597 Self::Bgp { patterns } => {
598 for pattern in patterns {
599 write!(f, "{pattern} .")?
600 }
601 Ok(())
602 }
603 Self::Path {
604 subject,
605 path,
606 object,
607 } => write!(f, "{subject} {path} {object} ."),
608 Self::Join { left, right } => {
609 #[allow(clippy::match_same_arms)]
610 match right.as_ref() {
611 Self::LeftJoin { .. }
612 | Self::Minus { .. }
613 | Self::Extend { .. }
614 | Self::Filter { .. } => {
615 write!(f, "{left} {{ {right} }}")
617 }
618 #[cfg(feature = "sep-0006")]
619 Self::Lateral { .. } => {
620 write!(f, "{left} {{ {right} }}")
621 }
622 _ => write!(f, "{left} {right}"),
623 }
624 }
625 Self::LeftJoin {
626 left,
627 right,
628 expression,
629 } => {
630 if let Some(expr) = expression {
631 write!(f, "{left} OPTIONAL {{ {right} FILTER({expr}) }}")
632 } else {
633 write!(f, "{left} OPTIONAL {{ {right} }}")
634 }
635 }
636 #[cfg(feature = "sep-0006")]
637 Self::Lateral { left, right } => {
638 write!(f, "{left} LATERAL {{ {right} }}")
639 }
640 Self::Filter { expr, inner } => {
641 write!(f, "{inner} FILTER({expr})")
642 }
643 Self::Union { left, right } => write!(f, "{{ {left} }} UNION {{ {right} }}"),
644 Self::Graph { name, inner } => {
645 write!(f, "GRAPH {name} {{ {inner} }}")
646 }
647 Self::Extend {
648 inner,
649 variable,
650 expression,
651 } => write!(f, "{inner} BIND({expression} AS {variable})"),
652 Self::Minus { left, right } => write!(f, "{left} MINUS {{ {right} }}"),
653 Self::Service {
654 name,
655 inner,
656 silent,
657 } => {
658 if *silent {
659 write!(f, "SERVICE SILENT {name} {{ {inner} }}")
660 } else {
661 write!(f, "SERVICE {name} {{ {inner} }}")
662 }
663 }
664 Self::Values {
665 variables,
666 bindings,
667 } => {
668 f.write_str("VALUES ( ")?;
669 for var in variables {
670 write!(f, "{var} ")?;
671 }
672 f.write_str(") { ")?;
673 for row in bindings {
674 f.write_str("( ")?;
675 for val in row {
676 match val {
677 Some(val) => write!(f, "{val} "),
678 None => f.write_str("UNDEF "),
679 }?;
680 }
681 f.write_str(") ")?;
682 }
683 f.write_str(" }")
684 }
685 Self::Group {
686 inner,
687 variables,
688 aggregates,
689 } => {
690 f.write_str("{SELECT")?;
691 for (a, v) in aggregates {
692 write!(f, " ({v} AS {a})")?;
693 }
694 for b in variables {
695 write!(f, " {b}")?;
696 }
697 write!(f, " WHERE {{ {inner} }}")?;
698 if !variables.is_empty() {
699 f.write_str(" GROUP BY")?;
700 for v in variables {
701 write!(f, " {v}")?;
702 }
703 }
704 f.write_str("}")
705 }
706 p => write!(
707 f,
708 "{{ {} }}",
709 SparqlGraphRootPattern {
710 pattern: p,
711 dataset: None
712 }
713 ),
714 }
715 }
716}
717
718impl Default for GraphPattern {
719 fn default() -> Self {
720 Self::Bgp {
721 patterns: Vec::default(),
722 }
723 }
724}
725
726impl GraphPattern {
727 pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
729 match self {
730 Self::Bgp { patterns } => {
731 f.write_str("(bgp")?;
732 for pattern in patterns {
733 f.write_str(" ")?;
734 pattern.fmt_sse(f)?;
735 }
736 f.write_str(")")
737 }
738 Self::Path {
739 subject,
740 path,
741 object,
742 } => {
743 f.write_str("(path ")?;
744 subject.fmt_sse(f)?;
745 f.write_str(" ")?;
746 path.fmt_sse(f)?;
747 f.write_str(" ")?;
748 object.fmt_sse(f)?;
749 f.write_str(")")
750 }
751 Self::Join { left, right } => {
752 f.write_str("(join ")?;
753 left.fmt_sse(f)?;
754 f.write_str(" ")?;
755 right.fmt_sse(f)?;
756 f.write_str(")")
757 }
758 Self::LeftJoin {
759 left,
760 right,
761 expression,
762 } => {
763 f.write_str("(leftjoin ")?;
764 left.fmt_sse(f)?;
765 f.write_str(" ")?;
766 right.fmt_sse(f)?;
767 if let Some(expr) = expression {
768 f.write_str(" ")?;
769 expr.fmt_sse(f)?;
770 }
771 f.write_str(")")
772 }
773 #[cfg(feature = "sep-0006")]
774 Self::Lateral { left, right } => {
775 f.write_str("(lateral ")?;
776 left.fmt_sse(f)?;
777 f.write_str(" ")?;
778 right.fmt_sse(f)?;
779 f.write_str(")")
780 }
781 Self::Filter { expr, inner } => {
782 f.write_str("(filter ")?;
783 expr.fmt_sse(f)?;
784 f.write_str(" ")?;
785 inner.fmt_sse(f)?;
786 f.write_str(")")
787 }
788 Self::Union { left, right } => {
789 f.write_str("(union ")?;
790 left.fmt_sse(f)?;
791 f.write_str(" ")?;
792 right.fmt_sse(f)?;
793 f.write_str(")")
794 }
795 Self::Graph { name, inner } => {
796 f.write_str("(graph ")?;
797 name.fmt_sse(f)?;
798 f.write_str(" ")?;
799 inner.fmt_sse(f)?;
800 f.write_str(")")
801 }
802 Self::Extend {
803 inner,
804 variable,
805 expression,
806 } => {
807 write!(f, "(extend (({variable} ")?;
808 expression.fmt_sse(f)?;
809 f.write_str(")) ")?;
810 inner.fmt_sse(f)?;
811 f.write_str(")")
812 }
813 Self::Minus { left, right } => {
814 f.write_str("(minus ")?;
815 left.fmt_sse(f)?;
816 f.write_str(" ")?;
817 right.fmt_sse(f)?;
818 f.write_str(")")
819 }
820 Self::Service {
821 name,
822 inner,
823 silent,
824 } => {
825 f.write_str("(service ")?;
826 if *silent {
827 f.write_str("silent ")?;
828 }
829 name.fmt_sse(f)?;
830 f.write_str(" ")?;
831 inner.fmt_sse(f)?;
832 f.write_str(")")
833 }
834 Self::Group {
835 inner,
836 variables,
837 aggregates,
838 } => {
839 f.write_str("(group (")?;
840 for (i, v) in variables.iter().enumerate() {
841 if i > 0 {
842 f.write_str(" ")?;
843 }
844 write!(f, "{v}")?;
845 }
846 f.write_str(") (")?;
847 for (i, (v, a)) in aggregates.iter().enumerate() {
848 if i > 0 {
849 f.write_str(" ")?;
850 }
851 f.write_str("(")?;
852 a.fmt_sse(f)?;
853 write!(f, " {v})")?;
854 }
855 f.write_str(") ")?;
856 inner.fmt_sse(f)?;
857 f.write_str(")")
858 }
859 Self::Values {
860 variables,
861 bindings,
862 } => {
863 f.write_str("(table (vars")?;
864 for var in variables {
865 write!(f, " {var}")?;
866 }
867 f.write_str(")")?;
868 for row in bindings {
869 f.write_str(" (row")?;
870 for (value, var) in row.iter().zip(variables) {
871 if let Some(value) = value {
872 write!(f, " ({var} {value})")?;
873 }
874 }
875 f.write_str(")")?;
876 }
877 f.write_str(")")
878 }
879 Self::OrderBy { inner, expression } => {
880 f.write_str("(order (")?;
881 for (i, c) in expression.iter().enumerate() {
882 if i > 0 {
883 f.write_str(" ")?;
884 }
885 c.fmt_sse(f)?;
886 }
887 f.write_str(") ")?;
888 inner.fmt_sse(f)?;
889 f.write_str(")")
890 }
891 Self::Project { inner, variables } => {
892 f.write_str("(project (")?;
893 for (i, v) in variables.iter().enumerate() {
894 if i > 0 {
895 f.write_str(" ")?;
896 }
897 write!(f, "{v}")?;
898 }
899 f.write_str(") ")?;
900 inner.fmt_sse(f)?;
901 f.write_str(")")
902 }
903 Self::Distinct { inner } => {
904 f.write_str("(distinct ")?;
905 inner.fmt_sse(f)?;
906 f.write_str(")")
907 }
908 Self::Reduced { inner } => {
909 f.write_str("(reduced ")?;
910 inner.fmt_sse(f)?;
911 f.write_str(")")
912 }
913 Self::Slice {
914 inner,
915 start,
916 length,
917 } => {
918 if let Some(length) = length {
919 write!(f, "(slice {start} {length} ")?;
920 } else {
921 write!(f, "(slice {start} _ ")?;
922 }
923 inner.fmt_sse(f)?;
924 f.write_str(")")
925 }
926 }
927 }
928
929 pub fn on_in_scope_variable<'a>(&'a self, mut callback: impl FnMut(&'a Variable)) {
931 self.lookup_in_scope_variables(&mut callback)
932 }
933
934 fn lookup_in_scope_variables<'a>(&'a self, callback: &mut impl FnMut(&'a Variable)) {
935 #[allow(clippy::match_same_arms)]
936 match self {
937 Self::Bgp { patterns } => {
938 for pattern in patterns {
939 lookup_triple_pattern_variables(pattern, callback)
940 }
941 }
942 Self::Path {
943 subject, object, ..
944 } => {
945 if let TermPattern::Variable(s) = subject {
946 callback(s);
947 }
948 #[cfg(feature = "rdf-star")]
949 if let TermPattern::Triple(s) = subject {
950 lookup_triple_pattern_variables(s, callback)
951 }
952 if let TermPattern::Variable(o) = object {
953 callback(o);
954 }
955 #[cfg(feature = "rdf-star")]
956 if let TermPattern::Triple(o) = object {
957 lookup_triple_pattern_variables(o, callback)
958 }
959 }
960 Self::Join { left, right }
961 | Self::LeftJoin { left, right, .. }
962 | Self::Union { left, right } => {
963 left.lookup_in_scope_variables(callback);
964 right.lookup_in_scope_variables(callback);
965 }
966 #[cfg(feature = "sep-0006")]
967 Self::Lateral { left, right } => {
968 left.lookup_in_scope_variables(callback);
969 right.lookup_in_scope_variables(callback);
970 }
971 Self::Graph { name, inner } => {
972 if let NamedNodePattern::Variable(g) = &name {
973 callback(g);
974 }
975 inner.lookup_in_scope_variables(callback);
976 }
977 Self::Extend {
978 inner, variable, ..
979 } => {
980 callback(variable);
981 inner.lookup_in_scope_variables(callback);
982 }
983 Self::Minus { left, .. } => left.lookup_in_scope_variables(callback),
984 Self::Group {
985 variables,
986 aggregates,
987 ..
988 } => {
989 for v in variables {
990 callback(v);
991 }
992 for (v, _) in aggregates {
993 callback(v);
994 }
995 }
996 Self::Values { variables, .. } | Self::Project { variables, .. } => {
997 for v in variables {
998 callback(v);
999 }
1000 }
1001 Self::Service { inner, .. }
1002 | Self::Filter { inner, .. }
1003 | Self::OrderBy { inner, .. }
1004 | Self::Distinct { inner }
1005 | Self::Reduced { inner }
1006 | Self::Slice { inner, .. } => inner.lookup_in_scope_variables(callback),
1007 }
1008 }
1009}
1010
1011fn lookup_triple_pattern_variables<'a>(
1012 pattern: &'a TriplePattern,
1013 callback: &mut impl FnMut(&'a Variable),
1014) {
1015 if let TermPattern::Variable(s) = &pattern.subject {
1016 callback(s);
1017 }
1018 #[cfg(feature = "rdf-star")]
1019 if let TermPattern::Triple(s) = &pattern.subject {
1020 lookup_triple_pattern_variables(s, callback)
1021 }
1022 if let NamedNodePattern::Variable(p) = &pattern.predicate {
1023 callback(p);
1024 }
1025 if let TermPattern::Variable(o) = &pattern.object {
1026 callback(o);
1027 }
1028 #[cfg(feature = "rdf-star")]
1029 if let TermPattern::Triple(o) = &pattern.object {
1030 lookup_triple_pattern_variables(o, callback)
1031 }
1032}
1033
1034pub(crate) struct SparqlGraphRootPattern<'a> {
1035 pattern: &'a GraphPattern,
1036 dataset: Option<&'a QueryDataset>,
1037}
1038
1039impl<'a> SparqlGraphRootPattern<'a> {
1040 pub fn new(pattern: &'a GraphPattern, dataset: Option<&'a QueryDataset>) -> Self {
1041 Self { pattern, dataset }
1042 }
1043}
1044
1045impl fmt::Display for SparqlGraphRootPattern<'_> {
1046 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1047 let mut distinct = false;
1048 let mut reduced = false;
1049 let mut order = None;
1050 let mut start = 0;
1051 let mut length = None;
1052 let mut project: &[Variable] = &[];
1053
1054 let mut child = self.pattern;
1055 loop {
1056 match child {
1057 GraphPattern::OrderBy { inner, expression } => {
1058 order = Some(expression);
1059 child = inner;
1060 }
1061 GraphPattern::Project { inner, variables } if project.is_empty() => {
1062 project = variables;
1063 child = inner;
1064 }
1065 GraphPattern::Distinct { inner } => {
1066 distinct = true;
1067 child = inner;
1068 }
1069 GraphPattern::Reduced { inner } => {
1070 reduced = true;
1071 child = inner;
1072 }
1073 GraphPattern::Slice {
1074 inner,
1075 start: s,
1076 length: l,
1077 } => {
1078 start = *s;
1079 length = *l;
1080 child = inner;
1081 }
1082 p => {
1083 f.write_str("SELECT")?;
1084 if distinct {
1085 f.write_str(" DISTINCT")?;
1086 }
1087 if reduced {
1088 f.write_str(" REDUCED")?;
1089 }
1090 if project.is_empty() {
1091 f.write_str(" *")?;
1092 } else {
1093 for v in project {
1094 write!(f, " {v}")?;
1095 }
1096 }
1097 if let Some(dataset) = self.dataset {
1098 write!(f, " {dataset}")?;
1099 }
1100 write!(f, " WHERE {{ {p} }}")?;
1101 if let Some(order) = order {
1102 f.write_str(" ORDER BY")?;
1103 for c in order {
1104 write!(f, " {c}")?;
1105 }
1106 }
1107 if start > 0 {
1108 write!(f, " OFFSET {start}")?;
1109 }
1110 if let Some(length) = length {
1111 write!(f, " LIMIT {length}")?;
1112 }
1113 return Ok(());
1114 }
1115 }
1116 }
1117 }
1118}
1119
1120#[derive(Eq, PartialEq, Debug, Clone, Hash)]
1122pub enum AggregateExpression {
1123 CountSolutions { distinct: bool },
1125 FunctionCall {
1126 name: AggregateFunction,
1127 expr: Expression,
1128 distinct: bool,
1129 },
1130}
1131
1132impl AggregateExpression {
1133 pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
1135 match self {
1136 Self::CountSolutions { distinct } => {
1137 f.write_str("(count")?;
1138 if *distinct {
1139 f.write_str(" distinct")?;
1140 }
1141 f.write_str(")")
1142 }
1143 Self::FunctionCall {
1144 name:
1145 AggregateFunction::GroupConcat {
1146 separator: Some(separator),
1147 },
1148 expr,
1149 distinct,
1150 } => {
1151 f.write_str("(group_concat ")?;
1152 if *distinct {
1153 f.write_str("distinct ")?;
1154 }
1155 expr.fmt_sse(f)?;
1156 write!(f, " {})", LiteralRef::new_simple_literal(separator))
1157 }
1158 Self::FunctionCall {
1159 name,
1160 expr,
1161 distinct,
1162 } => {
1163 f.write_str("(")?;
1164 name.fmt_sse(f)?;
1165 f.write_str(" ")?;
1166 if *distinct {
1167 f.write_str("distinct ")?;
1168 }
1169 expr.fmt_sse(f)?;
1170 f.write_str(")")
1171 }
1172 }
1173 }
1174}
1175
1176impl fmt::Display for AggregateExpression {
1177 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1178 match self {
1179 Self::CountSolutions { distinct } => {
1180 if *distinct {
1181 f.write_str("COUNT(DISTINCT *)")
1182 } else {
1183 f.write_str("COUNT(*)")
1184 }
1185 }
1186 Self::FunctionCall {
1187 name:
1188 AggregateFunction::GroupConcat {
1189 separator: Some(separator),
1190 },
1191 expr,
1192 distinct,
1193 } => {
1194 if *distinct {
1195 write!(
1196 f,
1197 "GROUP_CONCAT(DISTINCT {}; SEPARATOR = {})",
1198 expr,
1199 LiteralRef::new_simple_literal(separator)
1200 )
1201 } else {
1202 write!(
1203 f,
1204 "GROUP_CONCAT({}; SEPARATOR = {})",
1205 expr,
1206 LiteralRef::new_simple_literal(separator)
1207 )
1208 }
1209 }
1210 Self::FunctionCall {
1211 name,
1212 expr,
1213 distinct,
1214 } => {
1215 if *distinct {
1216 write!(f, "{name}(DISTINCT {expr})")
1217 } else {
1218 write!(f, "{name}({expr})")
1219 }
1220 }
1221 }
1222 }
1223}
1224
1225#[derive(Eq, PartialEq, Debug, Clone, Hash)]
1227pub enum AggregateFunction {
1228 Count,
1230 Sum,
1232 Avg,
1234 Min,
1236 Max,
1238 GroupConcat {
1240 separator: Option<String>,
1241 },
1242 Sample,
1244 Custom(NamedNode),
1245}
1246
1247impl AggregateFunction {
1248 pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
1250 match self {
1251 Self::Count => f.write_str("count"),
1252 Self::Sum => f.write_str("sum"),
1253 Self::Avg => f.write_str("avg"),
1254 Self::Min => f.write_str("min"),
1255 Self::Max => f.write_str("max"),
1256 Self::GroupConcat { .. } => f.write_str("group_concat"),
1257 Self::Sample => f.write_str("sample"),
1258 Self::Custom(iri) => write!(f, "{iri}"),
1259 }
1260 }
1261}
1262
1263impl fmt::Display for AggregateFunction {
1264 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1265 match self {
1266 Self::Count => f.write_str("COUNT"),
1267 Self::Sum => f.write_str("SUM"),
1268 Self::Avg => f.write_str("AVG"),
1269 Self::Min => f.write_str("MIN"),
1270 Self::Max => f.write_str("MAX"),
1271 Self::GroupConcat { .. } => f.write_str("GROUP_CONCAT"),
1272 Self::Sample => f.write_str("SAMPLE"),
1273 Self::Custom(iri) => iri.fmt(f),
1274 }
1275 }
1276}
1277
1278#[derive(Eq, PartialEq, Debug, Clone, Hash)]
1280pub enum OrderExpression {
1281 Asc(Expression),
1283 Desc(Expression),
1285}
1286
1287impl OrderExpression {
1288 pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
1290 match self {
1291 Self::Asc(e) => {
1292 f.write_str("(asc ")?;
1293 e.fmt_sse(f)?;
1294 f.write_str(")")
1295 }
1296 Self::Desc(e) => {
1297 f.write_str("(desc ")?;
1298 e.fmt_sse(f)?;
1299 f.write_str(")")
1300 }
1301 }
1302 }
1303}
1304
1305impl fmt::Display for OrderExpression {
1306 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1307 match self {
1308 Self::Asc(e) => write!(f, "ASC({e})"),
1309 Self::Desc(e) => write!(f, "DESC({e})"),
1310 }
1311 }
1312}
1313
1314#[derive(Eq, PartialEq, Debug, Clone, Hash)]
1316pub struct QueryDataset {
1317 pub default: Vec<NamedNode>,
1318 pub named: Option<Vec<NamedNode>>,
1319}
1320
1321impl QueryDataset {
1322 pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
1324 f.write_str("(")?;
1325 for (i, graph_name) in self.default.iter().enumerate() {
1326 if i > 0 {
1327 f.write_str(" ")?;
1328 }
1329 write!(f, "{graph_name}")?;
1330 }
1331 if let Some(named) = &self.named {
1332 for (i, graph_name) in named.iter().enumerate() {
1333 if !self.default.is_empty() || i > 0 {
1334 f.write_str(" ")?;
1335 }
1336 write!(f, "(named {graph_name})")?;
1337 }
1338 }
1339 f.write_str(")")
1340 }
1341}
1342
1343impl fmt::Display for QueryDataset {
1344 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1345 for g in &self.default {
1346 write!(f, " FROM {g}")?;
1347 }
1348 if let Some(named) = &self.named {
1349 for g in named {
1350 write!(f, " FROM NAMED {g}")?;
1351 }
1352 }
1353 Ok(())
1354 }
1355}
1356
1357#[derive(Eq, PartialEq, Debug, Clone, Hash)]
1361pub enum GraphTarget {
1362 NamedNode(NamedNode),
1363 DefaultGraph,
1364 NamedGraphs,
1365 AllGraphs,
1366}
1367
1368impl GraphTarget {
1369 pub(crate) fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
1371 match self {
1372 Self::NamedNode(node) => write!(f, "{node}"),
1373 Self::DefaultGraph => f.write_str("default"),
1374 Self::NamedGraphs => f.write_str("named"),
1375 Self::AllGraphs => f.write_str("all"),
1376 }
1377 }
1378}
1379
1380impl fmt::Display for GraphTarget {
1381 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1382 match self {
1383 Self::NamedNode(node) => write!(f, "GRAPH {node}"),
1384 Self::DefaultGraph => f.write_str("DEFAULT"),
1385 Self::NamedGraphs => f.write_str("NAMED"),
1386 Self::AllGraphs => f.write_str("ALL"),
1387 }
1388 }
1389}
1390
1391impl From<NamedNode> for GraphTarget {
1392 fn from(node: NamedNode) -> Self {
1393 Self::NamedNode(node)
1394 }
1395}
1396
1397impl From<GraphName> for GraphTarget {
1398 fn from(graph_name: GraphName) -> Self {
1399 match graph_name {
1400 GraphName::NamedNode(node) => Self::NamedNode(node),
1401 GraphName::DefaultGraph => Self::DefaultGraph,
1402 }
1403 }
1404}
1405
1406#[inline]
1407fn fmt_sse_unary_expression(f: &mut impl fmt::Write, name: &str, e: &Expression) -> fmt::Result {
1408 write!(f, "({name} ")?;
1409 e.fmt_sse(f)?;
1410 f.write_str(")")
1411}
1412
1413#[inline]
1414fn fmt_sse_binary_expression(
1415 f: &mut impl fmt::Write,
1416 name: &str,
1417 a: &Expression,
1418 b: &Expression,
1419) -> fmt::Result {
1420 write!(f, "({name} ")?;
1421 a.fmt_sse(f)?;
1422 f.write_str(" ")?;
1423 b.fmt_sse(f)?;
1424 f.write_str(")")
1425}