1use oxrdf::vocab::xsd;
4use rand::random;
5use spargebra::algebra::{
6 AggregateExpression as AlAggregateExpression, AggregateFunction, Expression as AlExpression,
7 GraphPattern as AlGraphPattern, OrderExpression as AlOrderExpression,
8};
9pub use spargebra::algebra::{Function, PropertyPathExpression};
10use spargebra::term::{BlankNode, GroundSubject, TermPattern, TriplePattern};
11pub use spargebra::term::{
12 GroundTerm, GroundTermPattern, Literal, NamedNode, NamedNodePattern, Variable,
13};
14#[cfg(feature = "rdf-star")]
15use spargebra::term::{GroundTriple, GroundTriplePattern};
16use std::collections::hash_map::DefaultHasher;
17use std::collections::{HashMap, HashSet};
18use std::hash::{Hash, Hasher};
19use std::ops::{Add, BitAnd, BitOr, Div, Mul, Neg, Not, Sub};
20
21#[derive(Eq, PartialEq, Debug, Clone, Hash)]
23pub enum Expression {
24 NamedNode(NamedNode),
25 Literal(Literal),
26 Variable(Variable),
27 Or(Vec<Self>),
29 And(Vec<Self>),
31 Equal(Box<Self>, Box<Self>),
33 SameTerm(Box<Self>, Box<Self>),
35 Greater(Box<Self>, Box<Self>),
37 GreaterOrEqual(Box<Self>, Box<Self>),
38 Less(Box<Self>, Box<Self>),
40 LessOrEqual(Box<Self>, Box<Self>),
41 Add(Box<Self>, Box<Self>),
43 Subtract(Box<Self>, Box<Self>),
45 Multiply(Box<Self>, Box<Self>),
47 Divide(Box<Self>, Box<Self>),
49 UnaryPlus(Box<Self>),
51 UnaryMinus(Box<Self>),
53 Not(Box<Self>),
55 Exists(Box<GraphPattern>),
57 Bound(Variable),
59 If(Box<Self>, Box<Self>, Box<Self>),
61 Coalesce(Vec<Self>),
63 FunctionCall(Function, Vec<Self>),
65}
66
67impl Expression {
68 pub fn or_all(args: impl IntoIterator<Item = Self>) -> Self {
69 let args = args.into_iter();
70 let mut all = Vec::with_capacity(args.size_hint().0);
71 for arg in args {
72 if let Some(ebv) = arg.effective_boolean_value() {
73 if ebv {
74 return true.into();
75 }
76 } else if let Self::Or(args) = arg {
78 all.extend(args);
79 } else {
80 all.push(arg);
81 }
82 }
83 match all.len() {
84 0 => false.into(),
85 1 => {
86 let result = all.pop().unwrap();
87 if result.returns_boolean() {
88 result } else {
90 Self::And(vec![result])
91 }
92 }
93 _ => Self::Or(order_vec(all)),
94 }
95 }
96
97 pub fn and_all(args: impl IntoIterator<Item = Self>) -> Self {
98 let args = args.into_iter();
99 let mut all = Vec::with_capacity(args.size_hint().0);
100 for arg in args {
101 if let Some(ebv) = arg.effective_boolean_value() {
102 if !ebv {
103 return false.into();
104 }
105 } else if let Self::And(args) = arg {
107 all.extend(args);
108 } else {
109 all.push(arg);
110 }
111 }
112 match all.len() {
113 0 => true.into(),
114 1 => {
115 let result = all.pop().unwrap();
116 if result.returns_boolean() {
117 result
118 } else {
119 Self::And(vec![result])
120 }
121 }
122 _ => Self::And(order_vec(all)),
123 }
124 }
125
126 pub fn equal(left: Self, right: Self) -> Self {
127 match (left, right) {
128 (Self::NamedNode(left), Self::NamedNode(right)) => (left == right).into(),
129 (Self::Literal(left), Self::Literal(right)) if left == right => true.into(),
130 (left, right) => {
131 let (left, right) = order_pair(left, right);
132 Self::Equal(Box::new(left), Box::new(right))
133 }
134 }
135 }
136
137 pub fn same_term(left: Self, right: Self) -> Self {
138 match (left, right) {
139 (Self::NamedNode(left), Self::NamedNode(right)) => (left == right).into(),
140 (Self::Literal(left), Self::Literal(right)) if left == right => true.into(),
141 (left, right) => {
142 let (left, right) = order_pair(left, right);
143 Self::SameTerm(Box::new(left), Box::new(right))
144 }
145 }
146 }
147
148 pub fn greater(left: Self, right: Self) -> Self {
149 Self::Greater(Box::new(left), Box::new(right))
150 }
151
152 pub fn greater_or_equal(left: Self, right: Self) -> Self {
153 Self::GreaterOrEqual(Box::new(left), Box::new(right))
154 }
155
156 pub fn less(left: Self, right: Self) -> Self {
157 Self::Less(Box::new(left), Box::new(right))
158 }
159
160 pub fn less_or_equal(left: Self, right: Self) -> Self {
161 Self::LessOrEqual(Box::new(left), Box::new(right))
162 }
163
164 pub fn unary_plus(inner: Self) -> Self {
165 Self::UnaryPlus(Box::new(inner))
166 }
167
168 pub fn exists(inner: GraphPattern) -> Self {
169 if inner.is_empty() {
170 return false.into();
171 }
172 if inner.is_empty_singleton() {
173 return true.into();
174 }
175 Self::Exists(Box::new(inner))
176 }
177
178 pub fn if_cond(cond: Self, then: Self, els: Self) -> Self {
179 match cond.effective_boolean_value() {
180 Some(true) => then,
181 Some(false) => els,
182 None => Self::If(Box::new(cond), Box::new(then), Box::new(els)),
183 }
184 }
185
186 pub fn coalesce(args: Vec<Self>) -> Self {
187 Self::Coalesce(args)
188 }
189
190 pub fn call(name: Function, args: Vec<Self>) -> Self {
191 Self::FunctionCall(name, args)
192 }
193
194 pub fn effective_boolean_value(&self) -> Option<bool> {
195 if let Self::Literal(literal) = self {
196 match literal.datatype() {
197 xsd::BOOLEAN => match literal.value() {
198 "true" | "1" => Some(true),
199 "false" | "0" => Some(false),
200 _ => None, },
202 xsd::STRING => Some(!literal.value().is_empty()),
203 _ => None, }
205 } else {
206 None
207 }
208 }
209
210 pub fn used_variables(&self) -> HashSet<&Variable> {
211 let mut variables = HashSet::new();
212 self.lookup_used_variables(&mut |v| {
213 variables.insert(v);
214 });
215 variables
216 }
217
218 pub fn lookup_used_variables<'a>(&'a self, callback: &mut impl FnMut(&'a Variable)) {
219 match self {
220 Self::NamedNode(_) | Self::Literal(_) => {}
221 Self::Variable(v) | Self::Bound(v) => callback(v),
222 Self::Or(inner)
223 | Self::And(inner)
224 | Self::Coalesce(inner)
225 | Self::FunctionCall(_, inner) => {
226 for i in inner {
227 i.lookup_used_variables(callback);
228 }
229 }
230 Self::Equal(a, b)
231 | Self::SameTerm(a, b)
232 | Self::Greater(a, b)
233 | Self::GreaterOrEqual(a, b)
234 | Self::Less(a, b)
235 | Self::LessOrEqual(a, b)
236 | Self::Add(a, b)
237 | Self::Subtract(a, b)
238 | Self::Multiply(a, b)
239 | Self::Divide(a, b) => {
240 a.lookup_used_variables(callback);
241 b.lookup_used_variables(callback);
242 }
243 Self::UnaryPlus(i) | Self::UnaryMinus(i) | Self::Not(i) => {
244 i.lookup_used_variables(callback)
245 }
246 Self::Exists(e) => e.lookup_used_variables(callback),
247 Self::If(a, b, c) => {
248 a.lookup_used_variables(callback);
249 b.lookup_used_variables(callback);
250 c.lookup_used_variables(callback);
251 }
252 }
253 }
254
255 fn from_sparql_algebra(
256 expression: &AlExpression,
257 graph_name: Option<&NamedNodePattern>,
258 ) -> Self {
259 match expression {
260 AlExpression::NamedNode(node) => Self::NamedNode(node.clone()),
261 AlExpression::Literal(literal) => Self::Literal(literal.clone()),
262 AlExpression::Variable(variable) => Self::Variable(variable.clone()),
263 AlExpression::Or(left, right) => Self::Or(vec![
264 Self::from_sparql_algebra(left, graph_name),
265 Self::from_sparql_algebra(right, graph_name),
266 ]),
267 AlExpression::And(left, right) => Self::And(vec![
268 Self::from_sparql_algebra(left, graph_name),
269 Self::from_sparql_algebra(right, graph_name),
270 ]),
271 AlExpression::Equal(left, right) => Self::Equal(
272 Box::new(Self::from_sparql_algebra(left, graph_name)),
273 Box::new(Self::from_sparql_algebra(right, graph_name)),
274 ),
275 AlExpression::SameTerm(left, right) => Self::SameTerm(
276 Box::new(Self::from_sparql_algebra(left, graph_name)),
277 Box::new(Self::from_sparql_algebra(right, graph_name)),
278 ),
279 AlExpression::Greater(left, right) => Self::Greater(
280 Box::new(Self::from_sparql_algebra(left, graph_name)),
281 Box::new(Self::from_sparql_algebra(right, graph_name)),
282 ),
283 AlExpression::GreaterOrEqual(left, right) => Self::GreaterOrEqual(
284 Box::new(Self::from_sparql_algebra(left, graph_name)),
285 Box::new(Self::from_sparql_algebra(right, graph_name)),
286 ),
287 AlExpression::Less(left, right) => Self::Less(
288 Box::new(Self::from_sparql_algebra(left, graph_name)),
289 Box::new(Self::from_sparql_algebra(right, graph_name)),
290 ),
291 AlExpression::LessOrEqual(left, right) => Self::LessOrEqual(
292 Box::new(Self::from_sparql_algebra(left, graph_name)),
293 Box::new(Self::from_sparql_algebra(right, graph_name)),
294 ),
295 AlExpression::In(left, right) => {
296 let left = Self::from_sparql_algebra(left, graph_name);
297 match right.len() {
298 0 => Self::if_cond(left, false.into(), false.into()),
299 1 => Self::Equal(
300 Box::new(left),
301 Box::new(Self::from_sparql_algebra(&right[0], graph_name)),
302 ),
303 _ => Self::Or(
304 right
305 .iter()
306 .map(|e| {
307 Self::Equal(
308 Box::new(left.clone()),
309 Box::new(Self::from_sparql_algebra(e, graph_name)),
310 )
311 })
312 .collect(),
313 ),
314 }
315 }
316 AlExpression::Add(left, right) => Self::Add(
317 Box::new(Self::from_sparql_algebra(left, graph_name)),
318 Box::new(Self::from_sparql_algebra(right, graph_name)),
319 ),
320 AlExpression::Subtract(left, right) => Self::Subtract(
321 Box::new(Self::from_sparql_algebra(left, graph_name)),
322 Box::new(Self::from_sparql_algebra(right, graph_name)),
323 ),
324 AlExpression::Multiply(left, right) => Self::Multiply(
325 Box::new(Self::from_sparql_algebra(left, graph_name)),
326 Box::new(Self::from_sparql_algebra(right, graph_name)),
327 ),
328 AlExpression::Divide(left, right) => Self::Divide(
329 Box::new(Self::from_sparql_algebra(left, graph_name)),
330 Box::new(Self::from_sparql_algebra(right, graph_name)),
331 ),
332 AlExpression::UnaryPlus(inner) => {
333 Self::UnaryPlus(Box::new(Self::from_sparql_algebra(inner, graph_name)))
334 }
335 AlExpression::UnaryMinus(inner) => {
336 Self::UnaryMinus(Box::new(Self::from_sparql_algebra(inner, graph_name)))
337 }
338 AlExpression::Not(inner) => {
339 Self::Not(Box::new(Self::from_sparql_algebra(inner, graph_name)))
340 }
341 AlExpression::Exists(inner) => Self::Exists(Box::new(
342 GraphPattern::from_sparql_algebra(inner, graph_name, &mut HashMap::new()),
343 )),
344 AlExpression::Bound(variable) => Self::Bound(variable.clone()),
345 AlExpression::If(cond, yes, no) => Self::If(
346 Box::new(Self::from_sparql_algebra(cond, graph_name)),
347 Box::new(Self::from_sparql_algebra(yes, graph_name)),
348 Box::new(Self::from_sparql_algebra(no, graph_name)),
349 ),
350 AlExpression::Coalesce(inner) => Self::Coalesce(
351 inner
352 .iter()
353 .map(|e| Self::from_sparql_algebra(e, graph_name))
354 .collect(),
355 ),
356 AlExpression::FunctionCall(name, args) => Self::FunctionCall(
357 name.clone(),
358 args.iter()
359 .map(|e| Self::from_sparql_algebra(e, graph_name))
360 .collect(),
361 ),
362 }
363 }
364
365 fn returns_boolean(&self) -> bool {
366 match self {
367 Self::Or(_)
368 | Self::And(_)
369 | Self::Equal(_, _)
370 | Self::SameTerm(_, _)
371 | Self::Greater(_, _)
372 | Self::GreaterOrEqual(_, _)
373 | Self::Less(_, _)
374 | Self::LessOrEqual(_, _)
375 | Self::Not(_)
376 | Self::Exists(_)
377 | Self::Bound(_)
378 | Self::FunctionCall(
379 Function::IsBlank | Function::IsIri | Function::IsLiteral | Function::IsNumeric,
380 _,
381 ) => true,
382 #[cfg(feature = "rdf-star")]
383 Self::FunctionCall(Function::IsTriple, _) => true,
384 Self::Literal(literal) => literal.datatype() == xsd::BOOLEAN,
385 Self::If(_, a, b) => a.returns_boolean() && b.returns_boolean(),
386 _ => false,
387 }
388 }
389}
390
391impl From<NamedNode> for Expression {
392 fn from(value: NamedNode) -> Self {
393 Self::NamedNode(value)
394 }
395}
396
397impl From<Literal> for Expression {
398 fn from(value: Literal) -> Self {
399 Self::Literal(value)
400 }
401}
402
403impl From<GroundSubject> for Expression {
404 fn from(value: GroundSubject) -> Self {
405 match value {
406 GroundSubject::NamedNode(value) => value.into(),
407 #[cfg(feature = "rdf-star")]
408 GroundSubject::Triple(value) => (*value).into(),
409 }
410 }
411}
412
413impl From<GroundTerm> for Expression {
414 fn from(value: GroundTerm) -> Self {
415 match value {
416 GroundTerm::NamedNode(value) => value.into(),
417 GroundTerm::Literal(value) => value.into(),
418 #[cfg(feature = "rdf-star")]
419 GroundTerm::Triple(value) => (*value).into(),
420 }
421 }
422}
423
424impl From<NamedNodePattern> for Expression {
425 fn from(value: NamedNodePattern) -> Self {
426 match value {
427 NamedNodePattern::NamedNode(value) => value.into(),
428 NamedNodePattern::Variable(variable) => variable.into(),
429 }
430 }
431}
432
433impl From<GroundTermPattern> for Expression {
434 fn from(value: GroundTermPattern) -> Self {
435 match value {
436 GroundTermPattern::NamedNode(value) => value.into(),
437 GroundTermPattern::Literal(value) => value.into(),
438 #[cfg(feature = "rdf-star")]
439 GroundTermPattern::Triple(value) => (*value).into(),
440 GroundTermPattern::Variable(variable) => variable.into(),
441 }
442 }
443}
444
445#[cfg(feature = "rdf-star")]
446impl From<GroundTriple> for Expression {
447 fn from(value: GroundTriple) -> Self {
448 Self::FunctionCall(
449 Function::Triple,
450 vec![
451 value.subject.into(),
452 value.predicate.into(),
453 value.object.into(),
454 ],
455 )
456 }
457}
458
459#[cfg(feature = "rdf-star")]
460impl From<GroundTriplePattern> for Expression {
461 fn from(value: GroundTriplePattern) -> Self {
462 Self::FunctionCall(
463 Function::Triple,
464 vec![
465 value.subject.into(),
466 value.predicate.into(),
467 value.object.into(),
468 ],
469 )
470 }
471}
472
473impl From<Variable> for Expression {
474 fn from(value: Variable) -> Self {
475 Self::Variable(value)
476 }
477}
478
479impl From<bool> for Expression {
480 fn from(value: bool) -> Self {
481 Literal::from(value).into()
482 }
483}
484
485impl From<&Expression> for AlExpression {
486 fn from(expression: &Expression) -> Self {
487 match expression {
488 Expression::NamedNode(node) => Self::NamedNode(node.clone()),
489 Expression::Literal(literal) => Self::Literal(literal.clone()),
490 Expression::Variable(variable) => Self::Variable(variable.clone()),
491 Expression::Or(inner) => inner
492 .iter()
493 .map(Into::into)
494 .reduce(|a, b| Self::Or(Box::new(a), Box::new(b)))
495 .unwrap_or_else(|| Literal::from(false).into()),
496 Expression::And(inner) => inner
497 .iter()
498 .map(Into::into)
499 .reduce(|a, b| Self::And(Box::new(a), Box::new(b)))
500 .unwrap_or_else(|| Literal::from(true).into()),
501 Expression::Equal(left, right) => Self::Equal(
502 Box::new(left.as_ref().into()),
503 Box::new(right.as_ref().into()),
504 ),
505 Expression::SameTerm(left, right) => Self::SameTerm(
506 Box::new(left.as_ref().into()),
507 Box::new(right.as_ref().into()),
508 ),
509 Expression::Greater(left, right) => Self::Greater(
510 Box::new(left.as_ref().into()),
511 Box::new(right.as_ref().into()),
512 ),
513 Expression::GreaterOrEqual(left, right) => Self::GreaterOrEqual(
514 Box::new(left.as_ref().into()),
515 Box::new(right.as_ref().into()),
516 ),
517 Expression::Less(left, right) => Self::Less(
518 Box::new(left.as_ref().into()),
519 Box::new(right.as_ref().into()),
520 ),
521 Expression::LessOrEqual(left, right) => Self::LessOrEqual(
522 Box::new(left.as_ref().into()),
523 Box::new(right.as_ref().into()),
524 ),
525 Expression::Add(left, right) => Self::Add(
526 Box::new(left.as_ref().into()),
527 Box::new(right.as_ref().into()),
528 ),
529 Expression::Subtract(left, right) => Self::Subtract(
530 Box::new(left.as_ref().into()),
531 Box::new(right.as_ref().into()),
532 ),
533 Expression::Multiply(left, right) => Self::Multiply(
534 Box::new(left.as_ref().into()),
535 Box::new(right.as_ref().into()),
536 ),
537 Expression::Divide(left, right) => Self::Divide(
538 Box::new(left.as_ref().into()),
539 Box::new(right.as_ref().into()),
540 ),
541 Expression::UnaryPlus(inner) => Self::UnaryPlus(Box::new(inner.as_ref().into())),
542 Expression::UnaryMinus(inner) => Self::UnaryMinus(Box::new(inner.as_ref().into())),
543 Expression::Not(inner) => Self::Not(Box::new(inner.as_ref().into())),
544 Expression::Exists(inner) => Self::Exists(Box::new(inner.as_ref().into())),
545 Expression::Bound(variable) => Self::Bound(variable.clone()),
546 Expression::If(cond, yes, no) => Self::If(
547 Box::new(cond.as_ref().into()),
548 Box::new(yes.as_ref().into()),
549 Box::new(no.as_ref().into()),
550 ),
551 Expression::Coalesce(inner) => Self::Coalesce(inner.iter().map(Into::into).collect()),
552 Expression::FunctionCall(name, args) => {
553 Self::FunctionCall(name.clone(), args.iter().map(Into::into).collect())
554 }
555 }
556 }
557}
558
559impl BitAnd for Expression {
560 type Output = Self;
561
562 fn bitand(self, rhs: Self) -> Self::Output {
563 Self::and_all([self, rhs])
564 }
565}
566
567impl BitOr for Expression {
568 type Output = Self;
569
570 fn bitor(self, rhs: Self) -> Self {
571 Self::or_all([self, rhs])
572 }
573}
574
575impl Not for Expression {
576 type Output = Self;
577
578 fn not(self) -> Self {
579 if let Some(v) = self.effective_boolean_value() {
580 (!v).into()
581 } else if let Self::Not(v) = self {
582 if v.returns_boolean() {
583 *v
584 } else {
585 Self::And(vec![*v])
586 }
587 } else {
588 Self::Not(Box::new(self))
589 }
590 }
591}
592
593impl Add for Expression {
594 type Output = Self;
595
596 fn add(self, rhs: Self) -> Self {
597 let (left, right) = order_pair(self, rhs);
598 Self::Add(Box::new(left), Box::new(right))
599 }
600}
601
602impl Sub for Expression {
603 type Output = Self;
604
605 fn sub(self, rhs: Self) -> Self {
606 Self::Subtract(Box::new(self), Box::new(rhs))
607 }
608}
609
610impl Mul for Expression {
611 type Output = Self;
612
613 fn mul(self, rhs: Self) -> Self {
614 let (left, right) = order_pair(self, rhs);
615 Self::Multiply(Box::new(left), Box::new(right))
616 }
617}
618
619impl Div for Expression {
620 type Output = Self;
621
622 fn div(self, rhs: Self) -> Self {
623 Self::Divide(Box::new(self), Box::new(rhs))
624 }
625}
626
627impl Neg for Expression {
628 type Output = Self;
629
630 fn neg(self) -> Self {
631 Self::UnaryMinus(Box::new(self))
632 }
633}
634
635#[derive(Eq, PartialEq, Debug, Clone, Hash)]
637pub enum GraphPattern {
638 QuadPattern {
640 subject: GroundTermPattern,
641 predicate: NamedNodePattern,
642 object: GroundTermPattern,
643 graph_name: Option<NamedNodePattern>,
644 },
645 Path {
647 subject: GroundTermPattern,
648 path: PropertyPathExpression,
649 object: GroundTermPattern,
650 graph_name: Option<NamedNodePattern>,
651 },
652 Graph { graph_name: NamedNodePattern },
657 Join {
659 left: Box<Self>,
660 right: Box<Self>,
661 algorithm: JoinAlgorithm,
662 },
663 LeftJoin {
665 left: Box<Self>,
666 right: Box<Self>,
667 expression: Expression,
668 algorithm: LeftJoinAlgorithm,
669 },
670 #[cfg(feature = "sep-0006")]
672 Lateral { left: Box<Self>, right: Box<Self> },
673 Filter {
675 expression: Expression,
676 inner: Box<Self>,
677 },
678 Union { inner: Vec<Self> },
680 Extend {
682 inner: Box<Self>,
683 variable: Variable,
684 expression: Expression,
685 },
686 Minus {
688 left: Box<Self>,
689 right: Box<Self>,
690 algorithm: MinusAlgorithm,
691 },
692 Values {
694 variables: Vec<Variable>,
695 bindings: Vec<Vec<Option<GroundTerm>>>,
696 },
697 OrderBy {
699 inner: Box<Self>,
700 expression: Vec<OrderExpression>,
701 },
702 Project {
704 inner: Box<Self>,
705 variables: Vec<Variable>,
706 },
707 Distinct { inner: Box<Self> },
709 Reduced { inner: Box<Self> },
711 Slice {
713 inner: Box<Self>,
714 start: usize,
715 length: Option<usize>,
716 },
717 Group {
719 inner: Box<Self>,
720 variables: Vec<Variable>,
721 aggregates: Vec<(Variable, AggregateExpression)>,
722 },
723 Service {
725 name: NamedNodePattern,
726 inner: Box<Self>,
727 silent: bool,
728 },
729}
730
731impl GraphPattern {
732 pub fn empty() -> Self {
733 Self::Values {
734 variables: Vec::new(),
735 bindings: Vec::new(),
736 }
737 }
738
739 fn is_empty(&self) -> bool {
741 if let Self::Values { bindings, .. } = self {
742 bindings.is_empty()
743 } else {
744 false
745 }
746 }
747
748 pub fn empty_singleton() -> Self {
749 Self::Values {
750 variables: Vec::new(),
751 bindings: vec![Vec::new()],
752 }
753 }
754
755 pub fn is_empty_singleton(&self) -> bool {
756 if let Self::Values { bindings, .. } = self {
757 bindings.len() == 1 && bindings.iter().all(|b| b.iter().all(Option::is_none))
758 } else {
759 false
760 }
761 }
762
763 pub fn join(left: Self, right: Self, algorithm: JoinAlgorithm) -> Self {
764 if left.is_empty() || right.is_empty() {
765 return Self::empty();
766 }
767 if left.is_empty_singleton() {
768 return right;
769 }
770 if right.is_empty_singleton() {
771 return left;
772 }
773 Self::Join {
774 left: Box::new(left),
775 right: Box::new(right),
776 algorithm,
777 }
778 }
779
780 #[cfg(feature = "sep-0006")]
781 pub fn lateral(left: Self, right: Self) -> Self {
782 if left.is_empty() || right.is_empty() {
783 return Self::empty();
784 }
785 if left.is_empty_singleton() {
786 return right;
787 }
788 if right.is_empty_singleton() {
789 return left;
790 }
791 Self::Lateral {
792 left: Box::new(left),
793 right: Box::new(right),
794 }
795 }
796
797 pub fn left_join(
798 left: Self,
799 right: Self,
800 expression: Expression,
801 algorithm: LeftJoinAlgorithm,
802 ) -> Self {
803 let expression_ebv = expression.effective_boolean_value();
804 if left.is_empty()
805 || right.is_empty()
806 || right.is_empty_singleton()
807 || expression_ebv == Some(false)
808 {
809 return left;
810 }
811 Self::LeftJoin {
812 left: Box::new(left),
813 right: Box::new(right),
814 expression: if expression_ebv == Some(true) {
815 true.into()
816 } else {
817 expression
818 },
819 algorithm,
820 }
821 }
822
823 pub fn minus(left: Self, right: Self, algorithm: MinusAlgorithm) -> Self {
824 if left.is_empty() {
825 return Self::empty();
826 }
827 if right.is_empty() {
828 return left;
829 }
830 Self::Minus {
831 left: Box::new(left),
832 right: Box::new(right),
833 algorithm,
834 }
835 }
836
837 pub fn union(left: Self, right: Self) -> Self {
838 Self::union_all([left, right])
839 }
840
841 pub fn union_all(args: impl IntoIterator<Item = Self>) -> Self {
842 let args = args.into_iter();
843 let mut all = Vec::with_capacity(args.size_hint().0);
844 for arg in args {
845 if arg.is_empty() {
846 continue;
847 }
848 if let Self::Union { inner } = arg {
849 all.extend(inner);
850 } else {
851 all.push(arg);
852 }
853 }
854 if all.is_empty() {
855 Self::empty()
856 } else {
857 Self::Union {
858 inner: order_vec(all),
859 }
860 }
861 }
862
863 pub fn filter(inner: Self, expression: Expression) -> Self {
864 if inner.is_empty() {
865 return Self::empty();
866 }
867 let expression = match expression {
869 Expression::And(mut l) if l.len() == 1 => l.pop().unwrap(),
870 e => e,
871 };
872 match expression.effective_boolean_value() {
873 Some(true) => inner,
874 Some(false) => Self::empty(),
875 None => match inner {
876 Self::Filter {
877 inner: nested_inner,
878 expression: e2,
879 } => Self::Filter {
880 inner: nested_inner,
881 expression: expression & e2,
882 },
883 _ => Self::Filter {
884 inner: Box::new(inner),
885 expression,
886 },
887 },
888 }
889 }
890
891 pub fn extend(inner: Self, variable: Variable, expression: Expression) -> Self {
892 if inner.is_empty() {
893 return Self::empty();
894 }
895 Self::Extend {
896 inner: Box::new(inner),
897 variable,
898 expression,
899 }
900 }
901
902 pub fn values(
903 mut variables: Vec<Variable>,
904 mut bindings: Vec<Vec<Option<GroundTerm>>>,
905 ) -> Self {
906 let empty_rows = (0..variables.len())
907 .filter(|row| !bindings.iter().any(|binding| binding.get(*row).is_some()))
908 .collect::<Vec<_>>();
909 if !empty_rows.is_empty() {
910 variables = variables
912 .into_iter()
913 .enumerate()
914 .filter_map(|(i, v)| {
915 if empty_rows.contains(&i) {
916 None
917 } else {
918 Some(v)
919 }
920 })
921 .collect();
922 bindings = bindings
923 .into_iter()
924 .map(|binding| {
925 binding
926 .into_iter()
927 .enumerate()
928 .filter_map(|(i, v)| {
929 if empty_rows.contains(&i) {
930 None
931 } else {
932 Some(v)
933 }
934 })
935 .collect()
936 })
937 .collect();
938 }
939 Self::Values {
940 variables,
941 bindings,
942 }
943 }
944
945 pub fn order_by(inner: Self, expression: Vec<OrderExpression>) -> Self {
946 if inner.is_empty() {
947 return Self::empty();
948 }
949 if expression.is_empty() {
950 return inner;
951 }
952 Self::OrderBy {
953 inner: Box::new(inner),
954 expression,
955 }
956 }
957
958 pub fn project(inner: Self, variables: Vec<Variable>) -> Self {
959 Self::Project {
960 inner: Box::new(inner),
961 variables,
962 }
963 }
964
965 pub fn distinct(inner: Self) -> Self {
966 if inner.is_empty() {
967 return Self::empty();
968 }
969 Self::Distinct {
970 inner: Box::new(inner),
971 }
972 }
973
974 pub fn reduced(inner: Self) -> Self {
975 if inner.is_empty() {
976 return Self::empty();
977 }
978 Self::Reduced {
979 inner: Box::new(inner),
980 }
981 }
982
983 pub fn slice(inner: Self, start: usize, length: Option<usize>) -> Self {
984 if inner.is_empty() {
985 return Self::empty();
986 }
987 if start == 0 && length.is_none() {
988 return inner;
989 }
990 Self::Slice {
991 inner: Box::new(inner),
992 start,
993 length,
994 }
995 }
996
997 pub fn group(
998 inner: Self,
999 variables: Vec<Variable>,
1000 aggregates: Vec<(Variable, AggregateExpression)>,
1001 ) -> Self {
1002 if inner.is_empty() {
1003 return Self::empty();
1004 }
1005 Self::Group {
1006 inner: Box::new(inner),
1007 variables,
1008 aggregates,
1009 }
1010 }
1011
1012 pub fn service(inner: Self, name: NamedNodePattern, silent: bool) -> Self {
1013 Self::Service {
1014 inner: Box::new(inner),
1015 name,
1016 silent,
1017 }
1018 }
1019
1020 pub fn lookup_used_variables<'a>(&'a self, callback: &mut impl FnMut(&'a Variable)) {
1021 match self {
1022 Self::Values { variables, .. } | Self::Project { variables, .. } => {
1023 for v in variables {
1024 callback(v);
1025 }
1026 }
1027 Self::QuadPattern {
1028 subject,
1029 predicate,
1030 object,
1031 graph_name,
1032 } => {
1033 lookup_term_pattern_variables(subject, callback);
1034 if let NamedNodePattern::Variable(v) = predicate {
1035 callback(v);
1036 }
1037 lookup_term_pattern_variables(object, callback);
1038 if let Some(NamedNodePattern::Variable(v)) = graph_name {
1039 callback(v);
1040 }
1041 }
1042 Self::Path {
1043 subject,
1044 object,
1045 graph_name,
1046 ..
1047 } => {
1048 lookup_term_pattern_variables(subject, callback);
1049 lookup_term_pattern_variables(object, callback);
1050 if let Some(NamedNodePattern::Variable(v)) = graph_name {
1051 callback(v);
1052 }
1053 }
1054 Self::Graph { graph_name } => {
1055 if let NamedNodePattern::Variable(v) = graph_name {
1056 callback(v);
1057 }
1058 }
1059 Self::Filter { inner, expression } => {
1060 expression.lookup_used_variables(callback);
1061 inner.lookup_used_variables(callback);
1062 }
1063 Self::Union { inner } => {
1064 for child in inner {
1065 child.lookup_used_variables(callback);
1066 }
1067 }
1068 Self::Join { left, right, .. } | Self::Minus { left, right, .. } => {
1069 left.lookup_used_variables(callback);
1070 right.lookup_used_variables(callback);
1071 }
1072 #[cfg(feature = "sep-0006")]
1073 Self::Lateral { left, right } => {
1074 left.lookup_used_variables(callback);
1075 right.lookup_used_variables(callback);
1076 }
1077 Self::LeftJoin {
1078 left,
1079 right,
1080 expression,
1081 ..
1082 } => {
1083 expression.lookup_used_variables(callback);
1084 left.lookup_used_variables(callback);
1085 right.lookup_used_variables(callback);
1086 }
1087 Self::Extend {
1088 inner,
1089 variable,
1090 expression,
1091 } => {
1092 callback(variable);
1093 expression.lookup_used_variables(callback);
1094 inner.lookup_used_variables(callback);
1095 }
1096 Self::OrderBy { inner, .. }
1097 | Self::Distinct { inner }
1098 | Self::Reduced { inner }
1099 | Self::Slice { inner, .. } => inner.lookup_used_variables(callback),
1100 Self::Service { inner, name, .. } => {
1101 if let NamedNodePattern::Variable(v) = name {
1102 callback(v);
1103 }
1104 inner.lookup_used_variables(callback);
1105 }
1106 Self::Group {
1107 variables,
1108 aggregates,
1109 ..
1110 } => {
1111 for v in variables {
1112 callback(v);
1113 }
1114 for (v, _) in aggregates {
1115 callback(v);
1116 }
1117 }
1118 }
1119 }
1120
1121 fn from_sparql_algebra(
1122 pattern: &AlGraphPattern,
1123 graph_name: Option<&NamedNodePattern>,
1124 blank_nodes: &mut HashMap<BlankNode, Variable>,
1125 ) -> Self {
1126 match pattern {
1127 AlGraphPattern::Bgp { patterns } => patterns
1128 .iter()
1129 .map(|p| {
1130 let (subject, predicate, object) =
1131 Self::triple_pattern_from_algebra(p, blank_nodes);
1132 Self::QuadPattern {
1133 subject,
1134 predicate,
1135 object,
1136 graph_name: graph_name.cloned(),
1137 }
1138 })
1139 .reduce(|a, b| Self::Join {
1140 left: Box::new(a),
1141 right: Box::new(b),
1142 algorithm: JoinAlgorithm::default(),
1143 })
1144 .unwrap_or_else(|| {
1145 if let Some(graph_name) = graph_name {
1146 Self::Graph {
1147 graph_name: graph_name.clone(),
1148 }
1149 } else {
1150 Self::empty_singleton()
1151 }
1152 }),
1153 AlGraphPattern::Path {
1154 subject,
1155 path,
1156 object,
1157 } => Self::Path {
1158 subject: Self::term_pattern_from_algebra(subject, blank_nodes),
1159 path: path.clone(),
1160 object: Self::term_pattern_from_algebra(object, blank_nodes),
1161 graph_name: graph_name.cloned(),
1162 },
1163 AlGraphPattern::Join { left, right } => Self::Join {
1164 left: Box::new(Self::from_sparql_algebra(left, graph_name, blank_nodes)),
1165 right: Box::new(Self::from_sparql_algebra(right, graph_name, blank_nodes)),
1166 algorithm: JoinAlgorithm::default(),
1167 },
1168 AlGraphPattern::LeftJoin {
1169 left,
1170 right,
1171 expression,
1172 } => Self::LeftJoin {
1173 left: Box::new(Self::from_sparql_algebra(left, graph_name, blank_nodes)),
1174 right: Box::new(Self::from_sparql_algebra(right, graph_name, blank_nodes)),
1175 expression: expression.as_ref().map_or_else(
1176 || true.into(),
1177 |e| Expression::from_sparql_algebra(e, graph_name),
1178 ),
1179 algorithm: LeftJoinAlgorithm::default(),
1180 },
1181 #[cfg(feature = "sep-0006")]
1182 AlGraphPattern::Lateral { left, right } => Self::Lateral {
1183 left: Box::new(Self::from_sparql_algebra(left, graph_name, blank_nodes)),
1184 right: Box::new(Self::from_sparql_algebra(right, graph_name, blank_nodes)),
1185 },
1186 AlGraphPattern::Filter { inner, expr } => Self::Filter {
1187 inner: Box::new(Self::from_sparql_algebra(inner, graph_name, blank_nodes)),
1188 expression: Expression::from_sparql_algebra(expr, graph_name),
1189 },
1190 AlGraphPattern::Union { left, right } => Self::Union {
1191 inner: vec![
1192 Self::from_sparql_algebra(left, graph_name, blank_nodes),
1193 Self::from_sparql_algebra(right, graph_name, blank_nodes),
1194 ],
1195 },
1196 AlGraphPattern::Graph { inner, name } => {
1197 Self::from_sparql_algebra(inner, Some(name), blank_nodes)
1198 }
1199 AlGraphPattern::Extend {
1200 inner,
1201 expression,
1202 variable,
1203 } => Self::Extend {
1204 inner: Box::new(Self::from_sparql_algebra(inner, graph_name, blank_nodes)),
1205 expression: Expression::from_sparql_algebra(expression, graph_name),
1206 variable: variable.clone(),
1207 },
1208 AlGraphPattern::Minus { left, right } => Self::Minus {
1209 left: Box::new(Self::from_sparql_algebra(left, graph_name, blank_nodes)),
1210 right: Box::new(Self::from_sparql_algebra(right, graph_name, blank_nodes)),
1211 algorithm: MinusAlgorithm::default(),
1212 },
1213 AlGraphPattern::Values {
1214 variables,
1215 bindings,
1216 } => Self::Values {
1217 variables: variables.clone(),
1218 bindings: bindings.clone(),
1219 },
1220 AlGraphPattern::OrderBy { inner, expression } => Self::OrderBy {
1221 inner: Box::new(Self::from_sparql_algebra(inner, graph_name, blank_nodes)),
1222 expression: expression
1223 .iter()
1224 .map(|e| OrderExpression::from_sparql_algebra(e, graph_name))
1225 .collect(),
1226 },
1227 AlGraphPattern::Project { inner, variables } => {
1228 let graph_name = if let Some(NamedNodePattern::Variable(graph_name)) = graph_name {
1229 Some(NamedNodePattern::Variable(
1230 if variables.contains(graph_name) {
1231 graph_name.clone()
1232 } else {
1233 new_var()
1234 },
1235 ))
1236 } else {
1237 graph_name.cloned()
1238 };
1239 Self::Project {
1240 inner: Box::new(Self::from_sparql_algebra(
1241 inner,
1242 graph_name.as_ref(),
1243 &mut HashMap::new(),
1244 )),
1245 variables: variables.clone(),
1246 }
1247 }
1248 AlGraphPattern::Distinct { inner } => Self::Distinct {
1249 inner: Box::new(Self::from_sparql_algebra(inner, graph_name, blank_nodes)),
1250 },
1251 AlGraphPattern::Reduced { inner } => Self::Distinct {
1252 inner: Box::new(Self::from_sparql_algebra(inner, graph_name, blank_nodes)),
1253 },
1254 AlGraphPattern::Slice {
1255 inner,
1256 start,
1257 length,
1258 } => Self::Slice {
1259 inner: Box::new(Self::from_sparql_algebra(inner, graph_name, blank_nodes)),
1260 start: *start,
1261 length: *length,
1262 },
1263 AlGraphPattern::Group {
1264 inner,
1265 variables,
1266 aggregates,
1267 } => Self::Group {
1268 inner: Box::new(Self::from_sparql_algebra(inner, graph_name, blank_nodes)),
1269 variables: variables.clone(),
1270 aggregates: aggregates
1271 .iter()
1272 .map(|(var, expr)| {
1273 (
1274 var.clone(),
1275 AggregateExpression::from_sparql_algebra(expr, graph_name),
1276 )
1277 })
1278 .collect(),
1279 },
1280 AlGraphPattern::Service {
1281 inner,
1282 name,
1283 silent,
1284 } => Self::Service {
1285 inner: Box::new(Self::from_sparql_algebra(inner, graph_name, blank_nodes)),
1286 name: name.clone(),
1287 silent: *silent,
1288 },
1289 }
1290 }
1291
1292 fn triple_pattern_from_algebra(
1293 pattern: &TriplePattern,
1294 blank_nodes: &mut HashMap<BlankNode, Variable>,
1295 ) -> (GroundTermPattern, NamedNodePattern, GroundTermPattern) {
1296 (
1297 Self::term_pattern_from_algebra(&pattern.subject, blank_nodes),
1298 pattern.predicate.clone(),
1299 Self::term_pattern_from_algebra(&pattern.object, blank_nodes),
1300 )
1301 }
1302
1303 fn term_pattern_from_algebra(
1304 pattern: &TermPattern,
1305 blank_nodes: &mut HashMap<BlankNode, Variable>,
1306 ) -> GroundTermPattern {
1307 match pattern {
1308 TermPattern::NamedNode(node) => node.clone().into(),
1309 TermPattern::BlankNode(node) => blank_nodes
1310 .entry(node.clone())
1311 .or_insert_with(new_var)
1312 .clone()
1313 .into(),
1314 TermPattern::Literal(literal) => literal.clone().into(),
1315 #[cfg(feature = "rdf-star")]
1316 TermPattern::Triple(pattern) => {
1317 let (subject, predicate, object) =
1318 Self::triple_pattern_from_algebra(pattern, blank_nodes);
1319 GroundTriplePattern {
1320 subject,
1321 predicate,
1322 object,
1323 }
1324 .into()
1325 }
1326 TermPattern::Variable(variable) => variable.clone().into(),
1327 }
1328 }
1329}
1330
1331impl From<&AlGraphPattern> for GraphPattern {
1332 fn from(pattern: &AlGraphPattern) -> Self {
1333 Self::from_sparql_algebra(pattern, None, &mut HashMap::new())
1334 }
1335}
1336
1337impl From<&GraphPattern> for AlGraphPattern {
1338 fn from(pattern: &GraphPattern) -> Self {
1339 match pattern {
1340 GraphPattern::QuadPattern {
1341 subject,
1342 predicate,
1343 object,
1344 graph_name,
1345 } => {
1346 let pattern = Self::Bgp {
1347 patterns: vec![TriplePattern {
1348 subject: subject.clone().into(),
1349 predicate: predicate.clone(),
1350 object: object.clone().into(),
1351 }],
1352 };
1353 if let Some(graph_name) = graph_name {
1354 Self::Graph {
1355 inner: Box::new(pattern),
1356 name: graph_name.clone(),
1357 }
1358 } else {
1359 pattern
1360 }
1361 }
1362 GraphPattern::Path {
1363 subject,
1364 path,
1365 object,
1366 graph_name,
1367 } => {
1368 let pattern = Self::Path {
1369 subject: subject.clone().into(),
1370 path: path.clone(),
1371 object: object.clone().into(),
1372 };
1373 if let Some(graph_name) = graph_name {
1374 Self::Graph {
1375 inner: Box::new(pattern),
1376 name: graph_name.clone(),
1377 }
1378 } else {
1379 pattern
1380 }
1381 }
1382 GraphPattern::Graph { graph_name } => Self::Graph {
1383 inner: Box::new(AlGraphPattern::Bgp {
1384 patterns: Vec::new(),
1385 }),
1386 name: graph_name.clone(),
1387 },
1388 GraphPattern::Join { left, right, .. } => {
1389 match (left.as_ref().into(), right.as_ref().into()) {
1390 (Self::Bgp { patterns: mut left }, Self::Bgp { patterns: right }) => {
1391 left.extend(right);
1392 Self::Bgp { patterns: left }
1393 }
1394 (left, right) => Self::Join {
1395 left: Box::new(left),
1396 right: Box::new(right),
1397 },
1398 }
1399 }
1400 GraphPattern::LeftJoin {
1401 left,
1402 right,
1403 expression,
1404 ..
1405 } => {
1406 let empty_expr = if let Expression::Literal(l) = expression {
1407 l.datatype() == xsd::BOOLEAN && l.value() == "true"
1408 } else {
1409 false
1410 };
1411 Self::LeftJoin {
1412 left: Box::new(left.as_ref().into()),
1413 right: Box::new(right.as_ref().into()),
1414 expression: if empty_expr {
1415 None
1416 } else {
1417 Some(expression.into())
1418 },
1419 }
1420 }
1421 #[cfg(feature = "sep-0006")]
1422 GraphPattern::Lateral { left, right } => {
1423 match (left.as_ref().into(), right.as_ref().into()) {
1424 (Self::Bgp { patterns: mut left }, Self::Bgp { patterns: right }) => {
1425 left.extend(right);
1426 Self::Bgp { patterns: left }
1427 }
1428 (left, right) => Self::Lateral {
1429 left: Box::new(left),
1430 right: Box::new(right),
1431 },
1432 }
1433 }
1434 GraphPattern::Filter { inner, expression } => Self::Filter {
1435 inner: Box::new(inner.as_ref().into()),
1436 expr: expression.into(),
1437 },
1438 GraphPattern::Union { inner } => inner
1439 .iter()
1440 .map(Into::into)
1441 .reduce(|a, b| Self::Union {
1442 left: Box::new(a),
1443 right: Box::new(b),
1444 })
1445 .unwrap_or_else(|| Self::Values {
1446 variables: Vec::new(),
1447 bindings: Vec::new(),
1448 }),
1449 GraphPattern::Extend {
1450 inner,
1451 expression,
1452 variable,
1453 } => Self::Extend {
1454 inner: Box::new(inner.as_ref().into()),
1455 expression: expression.into(),
1456 variable: variable.clone(),
1457 },
1458 GraphPattern::Minus { left, right, .. } => Self::Minus {
1459 left: Box::new(left.as_ref().into()),
1460 right: Box::new(right.as_ref().into()),
1461 },
1462 GraphPattern::Values {
1463 variables,
1464 bindings,
1465 } => Self::Values {
1466 variables: variables.clone(),
1467 bindings: bindings.clone(),
1468 },
1469 GraphPattern::OrderBy { inner, expression } => Self::OrderBy {
1470 inner: Box::new(inner.as_ref().into()),
1471 expression: expression.iter().map(Into::into).collect(),
1472 },
1473 GraphPattern::Project { inner, variables } => Self::Project {
1474 inner: Box::new(inner.as_ref().into()),
1475 variables: variables.clone(),
1476 },
1477 GraphPattern::Distinct { inner } => Self::Distinct {
1478 inner: Box::new(inner.as_ref().into()),
1479 },
1480 GraphPattern::Reduced { inner } => Self::Distinct {
1481 inner: Box::new(inner.as_ref().into()),
1482 },
1483 GraphPattern::Slice {
1484 inner,
1485 start,
1486 length,
1487 } => Self::Slice {
1488 inner: Box::new(inner.as_ref().into()),
1489 start: *start,
1490 length: *length,
1491 },
1492 GraphPattern::Group {
1493 inner,
1494 variables,
1495 aggregates,
1496 } => Self::Group {
1497 inner: Box::new(inner.as_ref().into()),
1498 variables: variables.clone(),
1499 aggregates: aggregates
1500 .iter()
1501 .map(|(var, expr)| (var.clone(), expr.into()))
1502 .collect(),
1503 },
1504 GraphPattern::Service {
1505 inner,
1506 name,
1507 silent,
1508 } => Self::Service {
1509 inner: Box::new(inner.as_ref().into()),
1510 name: name.clone(),
1511 silent: *silent,
1512 },
1513 }
1514 }
1515}
1516
1517#[derive(Eq, PartialEq, Debug, Clone, Hash)]
1519pub enum JoinAlgorithm {
1520 HashBuildLeftProbeRight { keys: Vec<Variable> },
1521}
1522
1523impl Default for JoinAlgorithm {
1524 fn default() -> Self {
1525 Self::HashBuildLeftProbeRight {
1526 keys: Vec::default(),
1527 }
1528 }
1529}
1530
1531#[derive(Eq, PartialEq, Debug, Clone, Hash)]
1533pub enum LeftJoinAlgorithm {
1534 HashBuildRightProbeLeft { keys: Vec<Variable> },
1535}
1536
1537impl Default for LeftJoinAlgorithm {
1538 fn default() -> Self {
1539 Self::HashBuildRightProbeLeft {
1540 keys: Vec::default(),
1541 }
1542 }
1543}
1544
1545#[derive(Eq, PartialEq, Debug, Clone, Hash)]
1547pub enum MinusAlgorithm {
1548 HashBuildRightProbeLeft { keys: Vec<Variable> },
1549}
1550
1551impl Default for MinusAlgorithm {
1552 fn default() -> Self {
1553 Self::HashBuildRightProbeLeft {
1554 keys: Vec::default(),
1555 }
1556 }
1557}
1558
1559#[derive(Eq, PartialEq, Debug, Clone, Hash)]
1561pub enum AggregateExpression {
1562 CountSolutions {
1563 distinct: bool,
1564 },
1565 FunctionCall {
1566 name: AggregateFunction,
1567 expr: Expression,
1568 distinct: bool,
1569 },
1570}
1571
1572impl AggregateExpression {
1573 fn from_sparql_algebra(
1574 expression: &AlAggregateExpression,
1575 graph_name: Option<&NamedNodePattern>,
1576 ) -> Self {
1577 match expression {
1578 AlAggregateExpression::CountSolutions { distinct } => Self::CountSolutions {
1579 distinct: *distinct,
1580 },
1581 AlAggregateExpression::FunctionCall {
1582 name,
1583 expr,
1584 distinct,
1585 } => Self::FunctionCall {
1586 name: name.clone(),
1587 expr: Expression::from_sparql_algebra(expr, graph_name),
1588 distinct: *distinct,
1589 },
1590 }
1591 }
1592}
1593
1594impl From<&AggregateExpression> for AlAggregateExpression {
1595 fn from(expression: &AggregateExpression) -> Self {
1596 match expression {
1597 AggregateExpression::CountSolutions { distinct } => Self::CountSolutions {
1598 distinct: *distinct,
1599 },
1600 AggregateExpression::FunctionCall {
1601 name,
1602 expr,
1603 distinct,
1604 } => Self::FunctionCall {
1605 name: name.clone(),
1606 expr: expr.into(),
1607 distinct: *distinct,
1608 },
1609 }
1610 }
1611}
1612
1613#[derive(Eq, PartialEq, Debug, Clone, Hash)]
1615pub enum OrderExpression {
1616 Asc(Expression),
1618 Desc(Expression),
1620}
1621
1622impl OrderExpression {
1623 fn from_sparql_algebra(
1624 expression: &AlOrderExpression,
1625 graph_name: Option<&NamedNodePattern>,
1626 ) -> Self {
1627 match expression {
1628 AlOrderExpression::Asc(e) => Self::Asc(Expression::from_sparql_algebra(e, graph_name)),
1629 AlOrderExpression::Desc(e) => {
1630 Self::Desc(Expression::from_sparql_algebra(e, graph_name))
1631 }
1632 }
1633 }
1634}
1635
1636impl From<&OrderExpression> for AlOrderExpression {
1637 fn from(expression: &OrderExpression) -> Self {
1638 match expression {
1639 OrderExpression::Asc(e) => Self::Asc(e.into()),
1640 OrderExpression::Desc(e) => Self::Desc(e.into()),
1641 }
1642 }
1643}
1644
1645fn new_var() -> Variable {
1646 Variable::new_unchecked(format!("{:x}", random::<u128>()))
1647}
1648
1649fn order_pair<T: Hash>(a: T, b: T) -> (T, T) {
1650 if hash(&a) <= hash(&b) {
1651 (a, b)
1652 } else {
1653 (b, a)
1654 }
1655}
1656
1657fn order_vec<T: Hash>(mut vec: Vec<T>) -> Vec<T> {
1658 vec.sort_unstable_by_key(|a| hash(a));
1659 vec
1660}
1661
1662fn hash(v: impl Hash) -> u64 {
1663 let mut hasher = DefaultHasher::new();
1664 v.hash(&mut hasher);
1665 hasher.finish()
1666}
1667
1668fn lookup_term_pattern_variables<'a>(
1669 pattern: &'a GroundTermPattern,
1670 callback: &mut impl FnMut(&'a Variable),
1671) {
1672 if let GroundTermPattern::Variable(v) = pattern {
1673 callback(v);
1674 }
1675 #[cfg(feature = "rdf-star")]
1676 if let GroundTermPattern::Triple(t) = pattern {
1677 lookup_term_pattern_variables(&t.subject, callback);
1678 if let NamedNodePattern::Variable(v) = &t.predicate {
1679 callback(v);
1680 }
1681 lookup_term_pattern_variables(&t.object, callback);
1682 }
1683}