spareval/
eval.rs

1#[cfg(feature = "rdf-star")]
2use crate::dataset::{ExpressionSubject, ExpressionTriple};
3use crate::dataset::{ExpressionTerm, InternalQuad, QueryableDataset};
4use crate::error::QueryEvaluationError;
5use crate::model::{QuerySolutionIter, QueryTripleIter};
6use crate::service::ServiceHandlerRegistry;
7use crate::CustomFunctionRegistry;
8use json_event_parser::{JsonEvent, WriterJsonSerializer};
9use md5::{Digest, Md5};
10use oxiri::Iri;
11use oxrdf::vocab::{rdf, xsd};
12use oxrdf::{BlankNode, Literal, NamedNode, Term, Triple, Variable};
13#[cfg(feature = "sep-0002")]
14use oxsdatatypes::{Date, Duration, Time, TimezoneOffset, YearMonthDuration};
15use oxsdatatypes::{DateTime, DayTimeDuration, Decimal, Double, Float, Integer};
16use rand::random;
17use regex::{Regex, RegexBuilder};
18use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet, FxHasher};
19use sha1::Sha1;
20use sha2::{Sha256, Sha384, Sha512};
21use spargebra::algebra::{AggregateFunction, Function, PropertyPathExpression};
22#[cfg(feature = "rdf-star")]
23use spargebra::term::GroundTriple;
24use spargebra::term::{
25    GroundTerm, GroundTermPattern, NamedNodePattern, TermPattern, TriplePattern,
26};
27use sparopt::algebra::{
28    AggregateExpression, Expression, GraphPattern, JoinAlgorithm, LeftJoinAlgorithm,
29    MinusAlgorithm, OrderExpression,
30};
31use std::borrow::Cow;
32use std::cell::{Cell, RefCell};
33use std::cmp::Ordering;
34use std::hash::{Hash, Hasher};
35use std::iter::{empty, once, Peekable};
36use std::rc::Rc;
37use std::sync::Arc;
38use std::{fmt, io};
39// TODO: make expression raise error when relevant (storage I/O)
40
41const REGEX_SIZE_LIMIT: usize = 1_000_000;
42
43/// Wrapper on top of [`QueryableDataset`]
44struct EvalDataset<D: QueryableDataset> {
45    dataset: Rc<D>,
46}
47
48impl<D: QueryableDataset> EvalDataset<D> {
49    fn internal_quads_for_pattern(
50        &self,
51        subject: Option<&D::InternalTerm>,
52        predicate: Option<&D::InternalTerm>,
53        object: Option<&D::InternalTerm>,
54        graph_name: Option<Option<&D::InternalTerm>>,
55    ) -> impl Iterator<Item = Result<InternalQuad<D>, QueryEvaluationError>> + 'static {
56        self.dataset
57            .internal_quads_for_pattern(subject, predicate, object, graph_name)
58            .map(|r| r.map_err(|e| QueryEvaluationError::Dataset(Box::new(e))))
59    }
60
61    fn internal_named_graphs(
62        &self,
63    ) -> impl Iterator<Item = Result<D::InternalTerm, QueryEvaluationError>> {
64        self.dataset
65            .internal_named_graphs()
66            .map(|r| r.map_err(|e| QueryEvaluationError::Dataset(Box::new(e))))
67    }
68
69    fn contains_internal_graph_name(
70        &self,
71        graph_name: &D::InternalTerm,
72    ) -> Result<bool, QueryEvaluationError> {
73        self.dataset
74            .contains_internal_graph_name(graph_name)
75            .map_err(|e| QueryEvaluationError::Dataset(Box::new(e)))
76    }
77
78    fn internalize_term(&self, term: Term) -> Result<D::InternalTerm, QueryEvaluationError> {
79        self.dataset
80            .internalize_term(term)
81            .map_err(|e| QueryEvaluationError::Dataset(Box::new(e)))
82    }
83
84    fn externalize_term(&self, term: D::InternalTerm) -> Result<Term, QueryEvaluationError> {
85        self.dataset
86            .externalize_term(term)
87            .map_err(|e| QueryEvaluationError::Dataset(Box::new(e)))
88    }
89
90    fn externalize_expression_term(
91        &self,
92        term: D::InternalTerm,
93    ) -> Result<ExpressionTerm, QueryEvaluationError> {
94        self.dataset
95            .externalize_expression_term(term)
96            .map_err(|e| QueryEvaluationError::Dataset(Box::new(e)))
97    }
98
99    fn internalize_expression_term(
100        &self,
101        term: ExpressionTerm,
102    ) -> Result<D::InternalTerm, QueryEvaluationError> {
103        self.dataset
104            .internalize_expression_term(term)
105            .map_err(|e| QueryEvaluationError::Dataset(Box::new(e)))
106    }
107
108    fn internal_term_effective_boolean_value(
109        &self,
110        term: D::InternalTerm,
111    ) -> Result<Option<bool>, QueryEvaluationError> {
112        self.dataset
113            .internal_term_effective_boolean_value(term)
114            .map_err(|e| QueryEvaluationError::Dataset(Box::new(e)))
115    }
116}
117
118impl<D: QueryableDataset> Clone for EvalDataset<D> {
119    #[inline]
120    fn clone(&self) -> Self {
121        Self {
122            dataset: Rc::clone(&self.dataset),
123        }
124    }
125}
126
127pub struct InternalTuple<D: QueryableDataset> {
128    inner: Vec<Option<D::InternalTerm>>,
129}
130
131impl<D: QueryableDataset> InternalTuple<D> {
132    pub fn with_capacity(capacity: usize) -> Self {
133        Self {
134            inner: Vec::with_capacity(capacity),
135        }
136    }
137
138    pub fn capacity(&self) -> usize {
139        self.inner.capacity()
140    }
141
142    pub fn contains(&self, index: usize) -> bool {
143        self.inner.get(index).is_some_and(Option::is_some)
144    }
145
146    pub fn get(&self, index: usize) -> Option<&D::InternalTerm> {
147        self.inner.get(index).unwrap_or(&None).as_ref()
148    }
149
150    pub fn iter(&self) -> impl Iterator<Item = Option<D::InternalTerm>> + '_ {
151        self.inner.iter().cloned()
152    }
153
154    pub fn set(&mut self, index: usize, value: D::InternalTerm) {
155        if self.inner.len() <= index {
156            self.inner.resize(index + 1, None);
157        }
158        self.inner[index] = Some(value);
159    }
160
161    pub fn combine_with(&self, other: &Self) -> Option<Self> {
162        if self.inner.len() < other.inner.len() {
163            let mut result = other.inner.clone();
164            for (key, self_value) in self.inner.iter().enumerate() {
165                if let Some(self_value) = self_value {
166                    match &other.inner[key] {
167                        Some(other_value) => {
168                            if self_value != other_value {
169                                return None;
170                            }
171                        }
172                        None => result[key] = Some(self_value.clone()),
173                    }
174                }
175            }
176            Some(Self { inner: result })
177        } else {
178            let mut result = self.inner.clone();
179            for (key, other_value) in other.inner.iter().enumerate() {
180                if let Some(other_value) = other_value {
181                    match &self.inner[key] {
182                        Some(self_value) => {
183                            if self_value != other_value {
184                                return None;
185                            }
186                        }
187                        None => result[key] = Some(other_value.clone()),
188                    }
189                }
190            }
191            Some(Self { inner: result })
192        }
193    }
194}
195
196impl<D: QueryableDataset> Clone for InternalTuple<D> {
197    fn clone(&self) -> Self {
198        Self {
199            inner: self.inner.clone(),
200        }
201    }
202}
203
204impl<D: QueryableDataset> PartialEq for InternalTuple<D> {
205    #[inline]
206    fn eq(&self, other: &InternalTuple<D>) -> bool {
207        self.inner == other.inner
208    }
209}
210
211impl<D: QueryableDataset> Eq for InternalTuple<D> {}
212
213impl<D: QueryableDataset> Hash for InternalTuple<D> {
214    fn hash<H: Hasher>(&self, state: &mut H) {
215        self.inner.hash(state)
216    }
217}
218
219impl<D: QueryableDataset> IntoIterator for InternalTuple<D> {
220    type Item = Option<D::InternalTerm>;
221    type IntoIter = std::vec::IntoIter<Option<D::InternalTerm>>;
222
223    fn into_iter(self) -> Self::IntoIter {
224        self.inner.into_iter()
225    }
226}
227
228type InternalTuplesIterator<D> =
229    Box<dyn Iterator<Item = Result<InternalTuple<D>, QueryEvaluationError>>>;
230
231pub struct SimpleEvaluator<D: QueryableDataset> {
232    dataset: EvalDataset<D>,
233    base_iri: Option<Rc<Iri<String>>>,
234    now: DateTime,
235    service_handler: Rc<ServiceHandlerRegistry>,
236    custom_functions: Rc<CustomFunctionRegistry>,
237    run_stats: bool,
238}
239
240impl<D: QueryableDataset> SimpleEvaluator<D> {
241    pub fn new(
242        dataset: D,
243        base_iri: Option<Rc<Iri<String>>>,
244        service_handler: Rc<ServiceHandlerRegistry>,
245        custom_functions: Rc<CustomFunctionRegistry>,
246        run_stats: bool,
247    ) -> Self {
248        Self {
249            dataset: EvalDataset {
250                dataset: Rc::new(dataset),
251            },
252            base_iri,
253            now: DateTime::now(),
254            service_handler,
255            custom_functions,
256            run_stats,
257        }
258    }
259
260    pub fn evaluate_select(
261        &self,
262        pattern: &GraphPattern,
263        substitutions: impl IntoIterator<Item = (Variable, Term)>,
264    ) -> (
265        Result<QuerySolutionIter, QueryEvaluationError>,
266        Rc<EvalNodeWithStats>,
267    ) {
268        let mut variables = Vec::new();
269        let (eval, stats) = self.graph_pattern_evaluator(pattern, &mut variables);
270        let from = match encode_initial_bindings(&self.dataset, &variables, substitutions) {
271            Ok(from) => from,
272            Err(e) => return (Err(e), stats),
273        };
274        (
275            Ok(decode_bindings(
276                self.dataset.clone(),
277                eval(from),
278                Arc::from(variables),
279            )),
280            stats,
281        )
282    }
283
284    pub fn evaluate_ask(
285        &self,
286        pattern: &GraphPattern,
287        substitutions: impl IntoIterator<Item = (Variable, Term)>,
288    ) -> (Result<bool, QueryEvaluationError>, Rc<EvalNodeWithStats>) {
289        let mut variables = Vec::new();
290        let (eval, stats) = self.graph_pattern_evaluator(pattern, &mut variables);
291        let from = match encode_initial_bindings(&self.dataset, &variables, substitutions) {
292            Ok(from) => from,
293            Err(e) => return (Err(e), stats),
294        };
295        // We apply the same table as the or operation:
296        // we return true if we get any valid tuple, an error if we get an error and false otherwise
297        let mut error = None;
298        for solution in eval(from) {
299            if let Err(e) = solution {
300                // We keep the first error
301                error.get_or_insert(e);
302            } else {
303                // We have found a valid tuple
304                return (Ok(true), stats);
305            }
306        }
307        (
308            if let Some(e) = error {
309                Err(e)
310            } else {
311                Ok(false)
312            },
313            stats,
314        )
315    }
316
317    pub fn evaluate_construct(
318        &self,
319        pattern: &GraphPattern,
320        template: &[TriplePattern],
321        substitutions: impl IntoIterator<Item = (Variable, Term)>,
322    ) -> (
323        Result<QueryTripleIter, QueryEvaluationError>,
324        Rc<EvalNodeWithStats>,
325    ) {
326        let mut variables = Vec::new();
327        let (eval, stats) = self.graph_pattern_evaluator(pattern, &mut variables);
328        let mut bnodes = Vec::new();
329        let template = template
330            .iter()
331            .filter_map(|t| {
332                Some(TripleTemplate {
333                    subject: TripleTemplateValue::from_term_or_variable(
334                        &t.subject,
335                        &mut variables,
336                        &mut bnodes,
337                    )?,
338                    predicate: TripleTemplateValue::from_named_node_or_variable(
339                        &t.predicate,
340                        &mut variables,
341                    ),
342                    object: TripleTemplateValue::from_term_or_variable(
343                        &t.object,
344                        &mut variables,
345                        &mut bnodes,
346                    )?,
347                })
348            })
349            .collect();
350        let from = match encode_initial_bindings(&self.dataset, &variables, substitutions) {
351            Ok(from) => from,
352            Err(e) => return (Err(e), stats),
353        };
354        (
355            Ok(QueryTripleIter::new(ConstructIterator {
356                eval: self.clone(),
357                iter: eval(from),
358                template,
359                buffered_results: Vec::default(),
360                already_emitted_results: FxHashSet::default(),
361                bnodes: Vec::default(),
362            })),
363            stats,
364        )
365    }
366
367    pub fn evaluate_describe(
368        &self,
369        pattern: &GraphPattern,
370        substitutions: impl IntoIterator<Item = (Variable, Term)>,
371    ) -> (
372        Result<QueryTripleIter, QueryEvaluationError>,
373        Rc<EvalNodeWithStats>,
374    ) {
375        let mut variables = Vec::new();
376        let (eval, stats) = self.graph_pattern_evaluator(pattern, &mut variables);
377        let from = match encode_initial_bindings(&self.dataset, &variables, substitutions) {
378            Ok(from) => from,
379            Err(e) => return (Err(e), stats),
380        };
381        (
382            Ok(QueryTripleIter::new(DescribeIterator {
383                eval: self.clone(),
384                tuples_to_describe: eval(from),
385                nodes_described: FxHashSet::default(),
386                nodes_to_describe: Vec::default(),
387                quads: Box::new(empty()),
388            })),
389            stats,
390        )
391    }
392
393    pub fn graph_pattern_evaluator(
394        &self,
395        pattern: &GraphPattern,
396        encoded_variables: &mut Vec<Variable>,
397    ) -> (
398        Rc<dyn Fn(InternalTuple<D>) -> InternalTuplesIterator<D>>,
399        Rc<EvalNodeWithStats>,
400    ) {
401        let mut stat_children = Vec::new();
402        let mut evaluator =
403            self.build_graph_pattern_evaluator(pattern, encoded_variables, &mut stat_children);
404        let stats = Rc::new(EvalNodeWithStats {
405            label: eval_node_label(pattern),
406            children: stat_children,
407            exec_count: Cell::new(0),
408            exec_duration: Cell::new(self.run_stats.then(DayTimeDuration::default)),
409        });
410        if self.run_stats {
411            let stats = Rc::clone(&stats);
412            evaluator = Rc::new(move |tuple| {
413                let start = Timer::now();
414                let inner = evaluator(tuple);
415                let duration = start.elapsed();
416                stats.exec_duration.set(
417                    stats
418                        .exec_duration
419                        .get()
420                        .and_then(|d| d.checked_add(duration?)),
421                );
422                Box::new(StatsIterator {
423                    inner,
424                    stats: Rc::clone(&stats),
425                })
426            })
427        }
428        (evaluator, stats)
429    }
430
431    fn build_graph_pattern_evaluator(
432        &self,
433        pattern: &GraphPattern,
434        encoded_variables: &mut Vec<Variable>,
435        stat_children: &mut Vec<Rc<EvalNodeWithStats>>,
436    ) -> Rc<dyn Fn(InternalTuple<D>) -> InternalTuplesIterator<D>> {
437        match pattern {
438            GraphPattern::Values {
439                variables,
440                bindings,
441            } => {
442                let encoding = variables
443                    .iter()
444                    .map(|v| encode_variable(encoded_variables, v))
445                    .collect::<Vec<_>>();
446                match bindings
447                    .iter()
448                    .map(|row| {
449                        let mut result = InternalTuple::with_capacity(variables.len());
450                        for (key, value) in row.iter().enumerate() {
451                            if let Some(term) = value {
452                                result.set(
453                                    encoding[key],
454                                    match term {
455                                        GroundTerm::NamedNode(node) => {
456                                            self.encode_term(node.clone())
457                                        }
458                                        GroundTerm::Literal(literal) => {
459                                            self.encode_term(literal.clone())
460                                        }
461                                        #[cfg(feature = "rdf-star")]
462                                        GroundTerm::Triple(triple) => self.encode_triple(triple),
463                                    }?,
464                                );
465                            }
466                        }
467                        Ok(result)
468                    })
469                    .collect::<Result<Vec<_>, _>>()
470                {
471                    Ok(encoded_tuples) => Rc::new(move |from| {
472                        Box::new(
473                            encoded_tuples
474                                .iter()
475                                .filter_map(move |t| t.combine_with(&from))
476                                .map(Ok)
477                                .collect::<Vec<_>>()
478                                .into_iter(),
479                        )
480                    }),
481                    Err(e) => error_evaluator(e),
482                }
483            }
484            GraphPattern::QuadPattern {
485                subject,
486                predicate,
487                object,
488                graph_name,
489            } => {
490                let subject_selector = match TupleSelector::from_ground_term_pattern(
491                    subject,
492                    encoded_variables,
493                    &self.dataset,
494                ) {
495                    Ok(selector) => selector,
496                    Err(e) => return error_evaluator(e),
497                };
498                let predicate_selector = match TupleSelector::from_named_node_pattern(
499                    predicate,
500                    encoded_variables,
501                    &self.dataset,
502                ) {
503                    Ok(selector) => selector,
504                    Err(e) => return error_evaluator(e),
505                };
506                let object_selector = match TupleSelector::from_ground_term_pattern(
507                    object,
508                    encoded_variables,
509                    &self.dataset,
510                ) {
511                    Ok(selector) => selector,
512                    Err(e) => return error_evaluator(e),
513                };
514                let graph_name_selector = if let Some(graph_name) = graph_name.as_ref() {
515                    match TupleSelector::from_named_node_pattern(
516                        graph_name,
517                        encoded_variables,
518                        &self.dataset,
519                    ) {
520                        Ok(selector) => Some(selector),
521                        Err(e) => return error_evaluator(e),
522                    }
523                } else {
524                    None
525                };
526                let dataset = self.dataset.clone();
527                Rc::new(move |from| {
528                    let input_subject = match subject_selector.get_pattern_value(
529                        &from,
530                        #[cfg(feature = "rdf-star")]
531                        &dataset,
532                    ) {
533                        Ok(value) => value,
534                        Err(e) => return Box::new(once(Err(e))),
535                    };
536                    let input_predicate = match predicate_selector.get_pattern_value(
537                        &from,
538                        #[cfg(feature = "rdf-star")]
539                        &dataset,
540                    ) {
541                        Ok(value) => value,
542                        Err(e) => return Box::new(once(Err(e))),
543                    };
544                    let input_object = match object_selector.get_pattern_value(
545                        &from,
546                        #[cfg(feature = "rdf-star")]
547                        &dataset,
548                    ) {
549                        Ok(value) => value,
550                        Err(e) => return Box::new(once(Err(e))),
551                    };
552                    let input_graph_name = if let Some(graph_name_selector) = &graph_name_selector {
553                        match graph_name_selector.get_pattern_value(
554                            &from,
555                            #[cfg(feature = "rdf-star")]
556                            &dataset,
557                        ) {
558                            Ok(value) => value,
559                            Err(e) => return Box::new(once(Err(e))),
560                        }
561                        .map(Some)
562                    } else {
563                        Some(None) // default graph
564                    };
565                    let iter = dataset.internal_quads_for_pattern(
566                        input_subject.as_ref(),
567                        input_predicate.as_ref(),
568                        input_object.as_ref(),
569                        input_graph_name.as_ref().map(|g| g.as_ref()),
570                    );
571                    let subject_selector = subject_selector.clone();
572                    let predicate_selector = predicate_selector.clone();
573                    let object_selector = object_selector.clone();
574                    let graph_name_selector = graph_name_selector.clone();
575                    #[cfg(feature = "rdf-star")]
576                    let dataset = dataset.clone();
577                    Box::new(
578                        iter.map(move |quad| {
579                            let quad = quad?;
580                            let mut new_tuple = from.clone();
581                            if !put_pattern_value(
582                                &subject_selector,
583                                quad.subject,
584                                &mut new_tuple,
585                                #[cfg(feature = "rdf-star")]
586                                &dataset,
587                            )? {
588                                return Ok(None);
589                            }
590                            if !put_pattern_value(
591                                &predicate_selector,
592                                quad.predicate,
593                                &mut new_tuple,
594                                #[cfg(feature = "rdf-star")]
595                                &dataset,
596                            )? {
597                                return Ok(None);
598                            }
599                            if !put_pattern_value(
600                                &object_selector,
601                                quad.object,
602                                &mut new_tuple,
603                                #[cfg(feature = "rdf-star")]
604                                &dataset,
605                            )? {
606                                return Ok(None);
607                            }
608                            if let Some(graph_name_selector) = &graph_name_selector {
609                                let Some(quad_graph_name) = quad.graph_name else {
610                                    return Err(QueryEvaluationError::UnexpectedDefaultGraph);
611                                };
612                                if !put_pattern_value(
613                                    graph_name_selector,
614                                    quad_graph_name,
615                                    &mut new_tuple,
616                                    #[cfg(feature = "rdf-star")]
617                                    &dataset,
618                                )? {
619                                    return Ok(None);
620                                }
621                            }
622                            Ok(Some(new_tuple))
623                        })
624                        .filter_map(Result::transpose),
625                    )
626                })
627            }
628            GraphPattern::Path {
629                subject,
630                path,
631                object,
632                graph_name,
633            } => {
634                let subject_selector = match TupleSelector::from_ground_term_pattern(
635                    subject,
636                    encoded_variables,
637                    &self.dataset,
638                ) {
639                    Ok(selector) => selector,
640                    Err(e) => return error_evaluator(e),
641                };
642                let path = match self.encode_property_path(path) {
643                    Ok(path) => path,
644                    Err(e) => return error_evaluator(e),
645                };
646                let object_selector = match TupleSelector::from_ground_term_pattern(
647                    object,
648                    encoded_variables,
649                    &self.dataset,
650                ) {
651                    Ok(selector) => selector,
652                    Err(e) => return error_evaluator(e),
653                };
654                let graph_name_selector = if let Some(graph_name) = graph_name.as_ref() {
655                    match TupleSelector::from_named_node_pattern(
656                        graph_name,
657                        encoded_variables,
658                        &self.dataset,
659                    ) {
660                        Ok(selector) => Some(selector),
661                        Err(e) => return error_evaluator(e),
662                    }
663                } else {
664                    None
665                };
666                let dataset = self.dataset.clone();
667                Rc::new(move |from| {
668                    let input_subject = match subject_selector.get_pattern_value(
669                        &from,
670                        #[cfg(feature = "rdf-star")]
671                        &dataset,
672                    ) {
673                        Ok(value) => value,
674                        Err(e) => return Box::new(once(Err(e))),
675                    };
676                    let path_eval = PathEvaluator {
677                        dataset: dataset.clone(),
678                    };
679                    let input_object = match object_selector.get_pattern_value(
680                        &from,
681                        #[cfg(feature = "rdf-star")]
682                        &dataset,
683                    ) {
684                        Ok(value) => value,
685                        Err(e) => return Box::new(once(Err(e))),
686                    };
687                    let input_graph_name = if let Some(graph_name_selector) = &graph_name_selector {
688                        match graph_name_selector.get_pattern_value(
689                            &from,
690                            #[cfg(feature = "rdf-star")]
691                            &dataset,
692                        ) {
693                            Ok(value) => value,
694                            Err(e) => return Box::new(once(Err(e))),
695                        }
696                        .map(Some)
697                    } else {
698                        Some(None) // default graph
699                    };
700                    match (input_subject, input_object, input_graph_name) {
701                        (Some(input_subject), Some(input_object), Some(input_graph_name)) => {
702                            match path_eval.eval_closed_in_graph(
703                                &path,
704                                &input_subject,
705                                &input_object,
706                                input_graph_name.as_ref(),
707                            ) {
708                                Ok(true) => Box::new(once(Ok(from))),
709                                Ok(false) => Box::new(empty()),
710                                Err(e) => Box::new(once(Err(e))),
711                            }
712                        }
713                        (Some(input_subject), None, Some(input_graph_name)) => {
714                            let object_selector = object_selector.clone();
715                            #[cfg(feature = "rdf-star")]
716                            let dataset = dataset.clone();
717                            Box::new(
718                                path_eval
719                                    .eval_from_in_graph(
720                                        &path,
721                                        &input_subject,
722                                        input_graph_name.as_ref(),
723                                    )
724                                    .map(move |o| {
725                                        let o = o?;
726                                        let mut new_tuple = from.clone();
727                                        if !put_pattern_value(
728                                            &object_selector,
729                                            o,
730                                            &mut new_tuple,
731                                            #[cfg(feature = "rdf-star")]
732                                            &dataset,
733                                        )? {
734                                            return Ok(None);
735                                        }
736                                        Ok(Some(new_tuple))
737                                    })
738                                    .filter_map(Result::transpose),
739                            )
740                        }
741                        (None, Some(input_object), Some(input_graph_name)) => {
742                            let subject_selector = subject_selector.clone();
743                            #[cfg(feature = "rdf-star")]
744                            let dataset = dataset.clone();
745                            Box::new(
746                                path_eval
747                                    .eval_to_in_graph(
748                                        &path,
749                                        &input_object,
750                                        input_graph_name.as_ref(),
751                                    )
752                                    .map(move |s| {
753                                        let s = s?;
754                                        let mut new_tuple = from.clone();
755                                        if !put_pattern_value(
756                                            &subject_selector,
757                                            s,
758                                            &mut new_tuple,
759                                            #[cfg(feature = "rdf-star")]
760                                            &dataset,
761                                        )? {
762                                            return Ok(None);
763                                        }
764                                        Ok(Some(new_tuple))
765                                    })
766                                    .filter_map(Result::transpose),
767                            )
768                        }
769                        (None, None, Some(input_graph_name)) => {
770                            let subject_selector = subject_selector.clone();
771                            let object_selector = object_selector.clone();
772                            #[cfg(feature = "rdf-star")]
773                            let dataset = dataset.clone();
774                            Box::new(
775                                path_eval
776                                    .eval_open_in_graph(&path, input_graph_name.as_ref())
777                                    .map(move |t| {
778                                        let (s, o) = t?;
779                                        let mut new_tuple = from.clone();
780                                        if !put_pattern_value(
781                                            &subject_selector,
782                                            s,
783                                            &mut new_tuple,
784                                            #[cfg(feature = "rdf-star")]
785                                            &dataset,
786                                        )? {
787                                            return Ok(None);
788                                        }
789                                        if !put_pattern_value(
790                                            &object_selector,
791                                            o,
792                                            &mut new_tuple,
793                                            #[cfg(feature = "rdf-star")]
794                                            &dataset,
795                                        )? {
796                                            return Ok(None);
797                                        }
798                                        Ok(Some(new_tuple))
799                                    })
800                                    .filter_map(Result::transpose),
801                            )
802                        }
803                        (Some(input_subject), Some(input_object), None) => {
804                            let graph_name_selector = graph_name_selector.clone();
805                            #[cfg(feature = "rdf-star")]
806                            let dataset = dataset.clone();
807                            Box::new(
808                                path_eval
809                                    .eval_closed_in_unknown_graph(
810                                        &path,
811                                        &input_subject,
812                                        &input_object,
813                                    )
814                                    .map(move |g| {
815                                        let g = g?;
816                                        let mut new_tuple = from.clone();
817                                        if let Some(graph_name_selector) = &graph_name_selector {
818                                            let Some(g) = g else {
819                                                return Err(
820                                                    QueryEvaluationError::UnexpectedDefaultGraph,
821                                                );
822                                            };
823                                            if !put_pattern_value(
824                                                graph_name_selector,
825                                                g,
826                                                &mut new_tuple,
827                                                #[cfg(feature = "rdf-star")]
828                                                &dataset,
829                                            )? {
830                                                return Ok(None);
831                                            }
832                                        }
833                                        Ok(Some(new_tuple))
834                                    })
835                                    .filter_map(Result::transpose),
836                            )
837                        }
838                        (Some(input_subject), None, None) => {
839                            let object_selector = object_selector.clone();
840                            let graph_name_selector = graph_name_selector.clone();
841                            #[cfg(feature = "rdf-star")]
842                            let dataset = dataset.clone();
843                            Box::new(
844                                path_eval
845                                    .eval_from_in_unknown_graph(&path, &input_subject)
846                                    .map(move |t| {
847                                        let (o, g) = t?;
848                                        let mut new_tuple = from.clone();
849                                        if !put_pattern_value(
850                                            &object_selector,
851                                            o,
852                                            &mut new_tuple,
853                                            #[cfg(feature = "rdf-star")]
854                                            &dataset,
855                                        )? {
856                                            return Ok(None);
857                                        }
858                                        if let Some(graph_name_selector) = &graph_name_selector {
859                                            let Some(g) = g else {
860                                                return Err(
861                                                    QueryEvaluationError::UnexpectedDefaultGraph,
862                                                );
863                                            };
864                                            if !put_pattern_value(
865                                                graph_name_selector,
866                                                g,
867                                                &mut new_tuple,
868                                                #[cfg(feature = "rdf-star")]
869                                                &dataset,
870                                            )? {
871                                                return Ok(None);
872                                            }
873                                        }
874                                        Ok(Some(new_tuple))
875                                    })
876                                    .filter_map(Result::transpose),
877                            )
878                        }
879                        (None, Some(input_object), None) => {
880                            let subject_selector = subject_selector.clone();
881                            let graph_name_selector = graph_name_selector.clone();
882                            #[cfg(feature = "rdf-star")]
883                            let dataset = dataset.clone();
884                            Box::new(
885                                path_eval
886                                    .eval_to_in_unknown_graph(&path, &input_object)
887                                    .map(move |t| {
888                                        let (s, g) = t?;
889                                        let mut new_tuple = from.clone();
890                                        if !put_pattern_value(
891                                            &subject_selector,
892                                            s,
893                                            &mut new_tuple,
894                                            #[cfg(feature = "rdf-star")]
895                                            &dataset,
896                                        )? {
897                                            return Ok(None);
898                                        }
899                                        if let Some(graph_name_selector) = &graph_name_selector {
900                                            let Some(g) = g else {
901                                                return Err(
902                                                    QueryEvaluationError::UnexpectedDefaultGraph,
903                                                );
904                                            };
905                                            if !put_pattern_value(
906                                                graph_name_selector,
907                                                g,
908                                                &mut new_tuple,
909                                                #[cfg(feature = "rdf-star")]
910                                                &dataset,
911                                            )? {
912                                                return Ok(None);
913                                            }
914                                        }
915                                        Ok(Some(new_tuple))
916                                    })
917                                    .filter_map(Result::transpose),
918                            )
919                        }
920                        (None, None, None) => {
921                            let subject_selector = subject_selector.clone();
922                            let object_selector = object_selector.clone();
923                            let graph_name_selector = graph_name_selector.clone();
924                            #[cfg(feature = "rdf-star")]
925                            let dataset = dataset.clone();
926                            Box::new(
927                                path_eval
928                                    .eval_open_in_unknown_graph(&path)
929                                    .map(move |t| {
930                                        let (s, o, g) = t?;
931                                        let mut new_tuple = from.clone();
932                                        if !put_pattern_value(
933                                            &subject_selector,
934                                            s,
935                                            &mut new_tuple,
936                                            #[cfg(feature = "rdf-star")]
937                                            &dataset,
938                                        )? {
939                                            return Ok(None);
940                                        }
941                                        if !put_pattern_value(
942                                            &object_selector,
943                                            o,
944                                            &mut new_tuple,
945                                            #[cfg(feature = "rdf-star")]
946                                            &dataset,
947                                        )? {
948                                            return Ok(None);
949                                        }
950                                        if let Some(graph_name_selector) = &graph_name_selector {
951                                            let Some(g) = g else {
952                                                return Err(
953                                                    QueryEvaluationError::UnexpectedDefaultGraph,
954                                                );
955                                            };
956                                            if !put_pattern_value(
957                                                graph_name_selector,
958                                                g,
959                                                &mut new_tuple,
960                                                #[cfg(feature = "rdf-star")]
961                                                &dataset,
962                                            )? {
963                                                return Ok(None);
964                                            }
965                                        }
966                                        Ok(Some(new_tuple))
967                                    })
968                                    .filter_map(Result::transpose),
969                            )
970                        }
971                    }
972                })
973            }
974            GraphPattern::Graph { graph_name } => {
975                let graph_name_selector = match TupleSelector::from_named_node_pattern(
976                    graph_name,
977                    encoded_variables,
978                    &self.dataset,
979                ) {
980                    Ok(selector) => selector,
981                    Err(e) => return error_evaluator(e),
982                };
983                let dataset = self.dataset.clone();
984                Rc::new(move |from| {
985                    let input_graph_name = match graph_name_selector.get_pattern_value(
986                        &from,
987                        #[cfg(feature = "rdf-star")]
988                        &dataset,
989                    ) {
990                        Ok(value) => value,
991                        Err(e) => return Box::new(once(Err(e))),
992                    };
993                    if let Some(input_graph_name) = input_graph_name {
994                        match dataset.contains_internal_graph_name(&input_graph_name) {
995                            Ok(true) => Box::new(once(Ok(from))),
996                            Ok(false) => Box::new(empty()),
997                            Err(e) => Box::new(once(Err(e))),
998                        }
999                    } else {
1000                        let graph_name_selector = graph_name_selector.clone();
1001                        #[cfg(feature = "rdf-star")]
1002                        let dataset = dataset.clone();
1003                        Box::new(
1004                            dataset
1005                                .internal_named_graphs()
1006                                .map(move |graph_name| {
1007                                    let graph_name = graph_name?;
1008                                    let mut new_tuple = from.clone();
1009                                    if !put_pattern_value(
1010                                        &graph_name_selector,
1011                                        graph_name,
1012                                        &mut new_tuple,
1013                                        #[cfg(feature = "rdf-star")]
1014                                        &dataset,
1015                                    )? {
1016                                        return Ok(None);
1017                                    }
1018                                    Ok(Some(new_tuple))
1019                                })
1020                                .filter_map(Result::transpose),
1021                        )
1022                    }
1023                })
1024            }
1025            GraphPattern::Join {
1026                left,
1027                right,
1028                algorithm,
1029            } => {
1030                let (left, left_stats) = self.graph_pattern_evaluator(left, encoded_variables);
1031                stat_children.push(left_stats);
1032                let (right, right_stats) = self.graph_pattern_evaluator(right, encoded_variables);
1033                stat_children.push(right_stats);
1034
1035                match algorithm {
1036                    JoinAlgorithm::HashBuildLeftProbeRight { keys } => {
1037                        let build = left;
1038                        let probe = right;
1039                        if keys.is_empty() {
1040                            // Cartesian product
1041                            Rc::new(move |from| {
1042                                let mut errors = Vec::default();
1043                                let built_values = build(from.clone())
1044                                    .filter_map(|result| match result {
1045                                        Ok(result) => Some(result),
1046                                        Err(error) => {
1047                                            errors.push(Err(error));
1048                                            None
1049                                        }
1050                                    })
1051                                    .collect::<Vec<_>>();
1052                                if built_values.is_empty() && errors.is_empty() {
1053                                    // We don't bother to execute the other side
1054                                    return Box::new(empty());
1055                                }
1056                                let mut probe_iter = probe(from).peekable();
1057                                if probe_iter.peek().is_none() {
1058                                    // We know it's empty and can discard errors
1059                                    return Box::new(empty());
1060                                }
1061                                Box::new(CartesianProductJoinIterator {
1062                                    probe_iter,
1063                                    built: built_values,
1064                                    buffered_results: errors,
1065                                })
1066                            })
1067                        } else {
1068                            // Real hash join
1069                            let keys = keys
1070                                .iter()
1071                                .map(|v| encode_variable(encoded_variables, v))
1072                                .collect::<Vec<_>>();
1073                            Rc::new(move |from| {
1074                                let mut errors = Vec::default();
1075                                let mut built_values = InternalTupleSet::new(keys.clone());
1076                                built_values.extend(build(from.clone()).filter_map(|result| {
1077                                    match result {
1078                                        Ok(result) => Some(result),
1079                                        Err(error) => {
1080                                            errors.push(Err(error));
1081                                            None
1082                                        }
1083                                    }
1084                                }));
1085                                if built_values.is_empty() && errors.is_empty() {
1086                                    // We don't bother to execute the other side
1087                                    return Box::new(empty());
1088                                }
1089                                let mut probe_iter = probe(from).peekable();
1090                                if probe_iter.peek().is_none() {
1091                                    // We know it's empty and can discard errors
1092                                    return Box::new(empty());
1093                                }
1094                                Box::new(HashJoinIterator {
1095                                    probe_iter,
1096                                    built: built_values,
1097                                    buffered_results: errors,
1098                                })
1099                            })
1100                        }
1101                    }
1102                }
1103            }
1104            #[cfg(feature = "sep-0006")]
1105            GraphPattern::Lateral { left, right } => {
1106                let (left, left_stats) = self.graph_pattern_evaluator(left, encoded_variables);
1107                stat_children.push(left_stats);
1108
1109                if let GraphPattern::LeftJoin {
1110                    left: nested_left,
1111                    right: nested_right,
1112                    expression,
1113                    ..
1114                } = right.as_ref()
1115                {
1116                    if nested_left.is_empty_singleton() {
1117                        // We are in a ForLoopLeftJoin
1118                        let right =
1119                            GraphPattern::filter(nested_right.as_ref().clone(), expression.clone());
1120                        let (right, right_stats) =
1121                            self.graph_pattern_evaluator(&right, encoded_variables);
1122                        stat_children.push(right_stats);
1123                        return Rc::new(move |from| {
1124                            Box::new(ForLoopLeftJoinIterator {
1125                                right_evaluator: Rc::clone(&right),
1126                                left_iter: left(from),
1127                                current_right: Box::new(empty()),
1128                                left_tuple_to_yield: None,
1129                            })
1130                        });
1131                    }
1132                }
1133                let (right, right_stats) = self.graph_pattern_evaluator(right, encoded_variables);
1134                stat_children.push(right_stats);
1135                Rc::new(move |from| {
1136                    let right = Rc::clone(&right);
1137                    Box::new(left(from).flat_map(move |t| match t {
1138                        Ok(t) => right(t),
1139                        Err(e) => Box::new(once(Err(e))),
1140                    }))
1141                })
1142            }
1143            GraphPattern::Minus {
1144                left,
1145                right,
1146                algorithm,
1147            } => {
1148                let (left, left_stats) = self.graph_pattern_evaluator(left, encoded_variables);
1149                stat_children.push(left_stats);
1150                let (right, right_stats) = self.graph_pattern_evaluator(right, encoded_variables);
1151                stat_children.push(right_stats);
1152
1153                match algorithm {
1154                    MinusAlgorithm::HashBuildRightProbeLeft { keys } => {
1155                        if keys.is_empty() {
1156                            Rc::new(move |from| {
1157                                let right: Vec<_> =
1158                                    right(from.clone()).filter_map(Result::ok).collect();
1159                                if right.is_empty() {
1160                                    return left(from);
1161                                }
1162                                Box::new(left(from).filter(move |left_tuple| {
1163                                    if let Ok(left_tuple) = left_tuple {
1164                                        !right.iter().any(|right_tuple| {
1165                                            are_compatible_and_not_disjointed(
1166                                                left_tuple,
1167                                                right_tuple,
1168                                            )
1169                                        })
1170                                    } else {
1171                                        true
1172                                    }
1173                                }))
1174                            })
1175                        } else {
1176                            let keys = keys
1177                                .iter()
1178                                .map(|v| encode_variable(encoded_variables, v))
1179                                .collect::<Vec<_>>();
1180                            Rc::new(move |from| {
1181                                let mut right_values = InternalTupleSet::new(keys.clone());
1182                                right_values.extend(right(from.clone()).filter_map(Result::ok));
1183                                if right_values.is_empty() {
1184                                    return left(from);
1185                                }
1186                                Box::new(left(from).filter(move |left_tuple| {
1187                                    if let Ok(left_tuple) = left_tuple {
1188                                        !right_values.get(left_tuple).iter().any(|right_tuple| {
1189                                            are_compatible_and_not_disjointed(
1190                                                left_tuple,
1191                                                right_tuple,
1192                                            )
1193                                        })
1194                                    } else {
1195                                        true
1196                                    }
1197                                }))
1198                            })
1199                        }
1200                    }
1201                }
1202            }
1203            GraphPattern::LeftJoin {
1204                left,
1205                right,
1206                expression,
1207                algorithm,
1208            } => {
1209                let (left, left_stats) = self.graph_pattern_evaluator(left, encoded_variables);
1210                stat_children.push(left_stats);
1211                let (right, right_stats) = self.graph_pattern_evaluator(right, encoded_variables);
1212                stat_children.push(right_stats);
1213                let expression = self.effective_boolean_value_expression_evaluator(
1214                    expression,
1215                    encoded_variables,
1216                    stat_children,
1217                );
1218
1219                match algorithm {
1220                    LeftJoinAlgorithm::HashBuildRightProbeLeft { keys } => {
1221                        // Real hash join
1222                        let keys = keys
1223                            .iter()
1224                            .map(|v| encode_variable(encoded_variables, v))
1225                            .collect::<Vec<_>>();
1226                        Rc::new(move |from| {
1227                            let mut errors = Vec::default();
1228                            let mut right_values = InternalTupleSet::new(keys.clone());
1229                            right_values.extend(right(from.clone()).filter_map(
1230                                |result| match result {
1231                                    Ok(result) => Some(result),
1232                                    Err(error) => {
1233                                        errors.push(Err(error));
1234                                        None
1235                                    }
1236                                },
1237                            ));
1238                            if right_values.is_empty() && errors.is_empty() {
1239                                return left(from);
1240                            }
1241                            Box::new(HashLeftJoinIterator {
1242                                left_iter: left(from),
1243                                right: right_values,
1244                                buffered_results: errors,
1245                                expression: Rc::clone(&expression),
1246                            })
1247                        })
1248                    }
1249                }
1250            }
1251            GraphPattern::Filter { inner, expression } => {
1252                let (child, child_stats) = self.graph_pattern_evaluator(inner, encoded_variables);
1253                stat_children.push(child_stats);
1254                let expression = self.effective_boolean_value_expression_evaluator(
1255                    expression,
1256                    encoded_variables,
1257                    stat_children,
1258                );
1259                Rc::new(move |from| {
1260                    let expression = Rc::clone(&expression);
1261                    Box::new(child(from).filter(move |tuple| match tuple {
1262                        Ok(tuple) => expression(tuple).unwrap_or(false),
1263                        Err(_) => true,
1264                    }))
1265                })
1266            }
1267            GraphPattern::Union { inner } => {
1268                let children = inner
1269                    .iter()
1270                    .map(|child| {
1271                        let (child, child_stats) =
1272                            self.graph_pattern_evaluator(child, encoded_variables);
1273                        stat_children.push(child_stats);
1274                        child
1275                    })
1276                    .collect::<Vec<_>>();
1277
1278                Rc::new(move |from| {
1279                    Box::new(UnionIterator {
1280                        plans: children.clone(),
1281                        input: from,
1282                        current_iterator: Box::new(empty()),
1283                        current_plan: 0,
1284                    })
1285                })
1286            }
1287            GraphPattern::Extend {
1288                inner,
1289                variable,
1290                expression,
1291            } => {
1292                let (child, child_stats) = self.graph_pattern_evaluator(inner, encoded_variables);
1293                stat_children.push(child_stats);
1294
1295                let position = encode_variable(encoded_variables, variable);
1296                if let Some(expression) =
1297                    self.internal_expression_evaluator(expression, encoded_variables, stat_children)
1298                {
1299                    return Rc::new(move |from| {
1300                        let expression = Rc::clone(&expression);
1301                        Box::new(child(from).map(move |tuple| {
1302                            let mut tuple = tuple?;
1303                            if let Some(value) = expression(&tuple) {
1304                                tuple.set(position, value);
1305                            }
1306                            Ok(tuple)
1307                        }))
1308                    });
1309                }
1310
1311                let expression =
1312                    self.expression_evaluator(expression, encoded_variables, stat_children);
1313                let dataset = self.dataset.clone();
1314                Rc::new(move |from| {
1315                    let expression = Rc::clone(&expression);
1316                    let dataset = dataset.clone();
1317                    Box::new(child(from).map(move |tuple| {
1318                        let mut tuple = tuple?;
1319                        if let Some(value) = expression(&tuple) {
1320                            tuple.set(position, dataset.internalize_expression_term(value)?);
1321                        }
1322                        Ok(tuple)
1323                    }))
1324                })
1325            }
1326            GraphPattern::OrderBy { inner, expression } => {
1327                let (child, child_stats) = self.graph_pattern_evaluator(inner, encoded_variables);
1328                stat_children.push(child_stats);
1329                let by = expression
1330                    .iter()
1331                    .map(|comp| match comp {
1332                        OrderExpression::Asc(expression) => ComparatorFunction::Asc(
1333                            self.expression_evaluator(expression, encoded_variables, stat_children),
1334                        ),
1335                        OrderExpression::Desc(expression) => ComparatorFunction::Desc(
1336                            self.expression_evaluator(expression, encoded_variables, stat_children),
1337                        ),
1338                    })
1339                    .collect::<Vec<_>>();
1340                Rc::new(move |from| {
1341                    let mut errors = Vec::default();
1342                    let mut values = child(from)
1343                        .filter_map(|result| match result {
1344                            Ok(result) => Some(result),
1345                            Err(error) => {
1346                                errors.push(Err(error));
1347                                None
1348                            }
1349                        })
1350                        .collect::<Vec<_>>();
1351                    values.sort_unstable_by(|a, b| {
1352                        for comp in &by {
1353                            match comp {
1354                                ComparatorFunction::Asc(expression) => {
1355                                    match cmp_terms(expression(a).as_ref(), expression(b).as_ref())
1356                                    {
1357                                        Ordering::Greater => return Ordering::Greater,
1358                                        Ordering::Less => return Ordering::Less,
1359                                        Ordering::Equal => (),
1360                                    }
1361                                }
1362                                ComparatorFunction::Desc(expression) => {
1363                                    match cmp_terms(expression(a).as_ref(), expression(b).as_ref())
1364                                    {
1365                                        Ordering::Greater => return Ordering::Less,
1366                                        Ordering::Less => return Ordering::Greater,
1367                                        Ordering::Equal => (),
1368                                    }
1369                                }
1370                            }
1371                        }
1372                        Ordering::Equal
1373                    });
1374                    Box::new(errors.into_iter().chain(values.into_iter().map(Ok)))
1375                })
1376            }
1377            GraphPattern::Distinct { inner } => {
1378                let (child, child_stats) = self.graph_pattern_evaluator(inner, encoded_variables);
1379                stat_children.push(child_stats);
1380                Rc::new(move |from| Box::new(hash_deduplicate(child(from))))
1381            }
1382            GraphPattern::Reduced { inner } => {
1383                let (child, child_stats) = self.graph_pattern_evaluator(inner, encoded_variables);
1384                stat_children.push(child_stats);
1385                Rc::new(move |from| {
1386                    Box::new(ConsecutiveDeduplication {
1387                        inner: child(from),
1388                        current: None,
1389                    })
1390                })
1391            }
1392            GraphPattern::Slice {
1393                inner,
1394                start,
1395                length,
1396            } => {
1397                let (mut child, child_stats) =
1398                    self.graph_pattern_evaluator(inner, encoded_variables);
1399                stat_children.push(child_stats);
1400                #[allow(clippy::shadow_same)]
1401                let start = *start;
1402                if start > 0 {
1403                    child = Rc::new(move |from| Box::new(child(from).skip(start)));
1404                }
1405                if let Some(length) = *length {
1406                    child = Rc::new(move |from| Box::new(child(from).take(length)));
1407                }
1408                child
1409            }
1410            GraphPattern::Project { inner, variables } => {
1411                let mut inner_encoded_variables = variables.clone();
1412                let (child, child_stats) =
1413                    self.graph_pattern_evaluator(inner, &mut inner_encoded_variables);
1414                stat_children.push(child_stats);
1415                let mapping = variables
1416                    .iter()
1417                    .enumerate()
1418                    .map(|(new_variable, variable)| {
1419                        (new_variable, encode_variable(encoded_variables, variable))
1420                    })
1421                    .collect::<Rc<[(usize, usize)]>>();
1422                Rc::new(move |from| {
1423                    let mapping = Rc::clone(&mapping);
1424                    let mut input_tuple = InternalTuple::with_capacity(mapping.len());
1425                    for (input_key, output_key) in &*mapping {
1426                        if let Some(value) = from.get(*output_key) {
1427                            input_tuple.set(*input_key, value.clone());
1428                        }
1429                    }
1430                    Box::new(child(input_tuple).filter_map(move |tuple| {
1431                        match tuple {
1432                            Ok(tuple) => {
1433                                let mut output_tuple = from.clone();
1434                                for (input_key, output_key) in &*mapping {
1435                                    if let Some(value) = tuple.get(*input_key) {
1436                                        if let Some(existing_value) = output_tuple.get(*output_key)
1437                                        {
1438                                            if existing_value != value {
1439                                                return None; // Conflict
1440                                            }
1441                                        } else {
1442                                            output_tuple.set(*output_key, value.clone());
1443                                        }
1444                                    }
1445                                }
1446                                Some(Ok(output_tuple))
1447                            }
1448                            Err(e) => Some(Err(e)),
1449                        }
1450                    }))
1451                })
1452            }
1453            GraphPattern::Group {
1454                inner,
1455                aggregates,
1456                variables,
1457            } => {
1458                let (child, child_stats) = self.graph_pattern_evaluator(inner, encoded_variables);
1459                stat_children.push(child_stats);
1460                let key_variables = variables
1461                    .iter()
1462                    .map(|k| encode_variable(encoded_variables, k))
1463                    .collect::<Rc<[_]>>();
1464                let accumulator_builders = aggregates
1465                    .iter()
1466                    .map(|(_, aggregate)| {
1467                        self.accumulator_builder(aggregate, encoded_variables, stat_children)
1468                    })
1469                    .collect::<Vec<_>>();
1470                let accumulator_variables = aggregates
1471                    .iter()
1472                    .map(|(variable, _)| encode_variable(encoded_variables, variable))
1473                    .collect::<Vec<_>>();
1474                let dataset = self.dataset.clone();
1475                Rc::new(move |from| {
1476                    let tuple_size = from.capacity();
1477                    let key_variables = Rc::clone(&key_variables);
1478                    let mut errors = Vec::default();
1479                    let mut accumulators_for_group = FxHashMap::<
1480                        Vec<Option<D::InternalTerm>>,
1481                        Vec<AccumulatorWrapper<D>>,
1482                    >::default();
1483                    if key_variables.is_empty() {
1484                        // There is always a single group if there is no GROUP BY
1485                        accumulators_for_group.insert(
1486                            Vec::new(),
1487                            accumulator_builders.iter().map(|c| c()).collect::<Vec<_>>(),
1488                        );
1489                    }
1490                    child(from)
1491                        .filter_map(|result| match result {
1492                            Ok(result) => Some(result),
1493                            Err(error) => {
1494                                errors.push(error);
1495                                None
1496                            }
1497                        })
1498                        .for_each(|tuple| {
1499                            // TODO avoid copy for key?
1500                            let key = key_variables
1501                                .iter()
1502                                .map(|v| tuple.get(*v).cloned())
1503                                .collect();
1504
1505                            let key_accumulators =
1506                                accumulators_for_group.entry(key).or_insert_with(|| {
1507                                    accumulator_builders.iter().map(|c| c()).collect::<Vec<_>>()
1508                                });
1509                            for accumulator in key_accumulators {
1510                                accumulator.add(&tuple);
1511                            }
1512                        });
1513                    let accumulator_variables = accumulator_variables.clone();
1514                    let dataset = dataset.clone();
1515                    Box::new(
1516                        errors
1517                            .into_iter()
1518                            .map(Err)
1519                            .chain(accumulators_for_group.into_iter().map(
1520                                move |(key, accumulators)| {
1521                                    let mut result = InternalTuple::with_capacity(tuple_size);
1522                                    for (variable, value) in key_variables.iter().zip(key) {
1523                                        if let Some(value) = value {
1524                                            result.set(*variable, value);
1525                                        }
1526                                    }
1527                                    for (accumulator, variable) in
1528                                        accumulators.into_iter().zip(&accumulator_variables)
1529                                    {
1530                                        if let Some(value) = accumulator.finish() {
1531                                            result.set(
1532                                                *variable,
1533                                                dataset.internalize_expression_term(value)?,
1534                                            );
1535                                        }
1536                                    }
1537                                    Ok(result)
1538                                },
1539                            )),
1540                    )
1541                })
1542            }
1543            GraphPattern::Service {
1544                name,
1545                inner,
1546                silent,
1547            } => {
1548                #[allow(clippy::shadow_same)]
1549                let silent = *silent;
1550                let service_name = match TupleSelector::from_named_node_pattern(
1551                    name,
1552                    encoded_variables,
1553                    &self.dataset,
1554                ) {
1555                    Ok(service_name) => service_name,
1556                    Err(e) => return error_evaluator(e),
1557                };
1558                self.build_graph_pattern_evaluator(inner, encoded_variables, &mut Vec::new()); // We call recursively to fill "encoded_variables"
1559                let graph_pattern = spargebra::algebra::GraphPattern::from(inner.as_ref());
1560                let variables = Rc::from(encoded_variables.as_slice());
1561                let eval = self.clone();
1562                Rc::new(move |from| {
1563                    match eval.evaluate_service(
1564                        &service_name,
1565                        &graph_pattern,
1566                        Rc::clone(&variables),
1567                        &from,
1568                    ) {
1569                        Ok(result) => Box::new(result.filter_map(move |binding| {
1570                            binding
1571                                .map(|binding| binding.combine_with(&from))
1572                                .transpose()
1573                        })),
1574                        Err(e) => {
1575                            if silent {
1576                                Box::new(once(Ok(from)))
1577                            } else {
1578                                Box::new(once(Err(e)))
1579                            }
1580                        }
1581                    }
1582                })
1583            }
1584        }
1585    }
1586
1587    fn evaluate_service(
1588        &self,
1589        service_name: &TupleSelector<D>,
1590        graph_pattern: &spargebra::algebra::GraphPattern,
1591        variables: Rc<[Variable]>,
1592        from: &InternalTuple<D>,
1593    ) -> Result<InternalTuplesIterator<D>, QueryEvaluationError> {
1594        let service_name = service_name
1595            .get_pattern_value(
1596                from,
1597                #[cfg(feature = "rdf-star")]
1598                &self.dataset,
1599            )?
1600            .ok_or(QueryEvaluationError::UnboundService)?;
1601        let service_name = match self.dataset.externalize_term(service_name)? {
1602            Term::NamedNode(service_name) => service_name,
1603            term => return Err(QueryEvaluationError::InvalidServiceName(term)),
1604        };
1605        let iter = self.service_handler.handle(
1606            service_name,
1607            graph_pattern.clone(),
1608            self.base_iri.as_ref().map(ToString::to_string),
1609        )?;
1610        Ok(encode_bindings(self.dataset.clone(), variables, iter))
1611    }
1612
1613    fn accumulator_builder(
1614        &self,
1615        expression: &AggregateExpression,
1616        encoded_variables: &mut Vec<Variable>,
1617        stat_children: &mut Vec<Rc<EvalNodeWithStats>>,
1618    ) -> Box<dyn Fn() -> AccumulatorWrapper<D>> {
1619        match expression {
1620            AggregateExpression::CountSolutions { distinct } => {
1621                if *distinct {
1622                    Box::new(move || AccumulatorWrapper::CountDistinctTuple {
1623                        count: 0,
1624                        seen: FxHashSet::default(),
1625                    })
1626                } else {
1627                    Box::new(move || AccumulatorWrapper::CountTuple { count: 0 })
1628                }
1629            }
1630            AggregateExpression::FunctionCall {
1631                name,
1632                distinct,
1633                expr,
1634            } => match name {
1635                AggregateFunction::Count => {
1636                    if let Some(evaluator) =
1637                        self.internal_expression_evaluator(expr, encoded_variables, stat_children)
1638                    {
1639                        return if *distinct {
1640                            Box::new(move || AccumulatorWrapper::CountDistinctInternal {
1641                                evaluator: Rc::clone(&evaluator),
1642                                seen: FxHashSet::default(),
1643                                count: 0,
1644                            })
1645                        } else {
1646                            Box::new(move || AccumulatorWrapper::CountInternal {
1647                                evaluator: Rc::clone(&evaluator),
1648                                count: 0,
1649                            })
1650                        };
1651                    }
1652                    let evaluator =
1653                        self.expression_evaluator(expr, encoded_variables, stat_children);
1654                    if *distinct {
1655                        Box::new(move || AccumulatorWrapper::DistinctExpression {
1656                            evaluator: Rc::clone(&evaluator),
1657                            seen: FxHashSet::default(),
1658                            accumulator: Some(Box::new(CountAccumulator::default())),
1659                        })
1660                    } else {
1661                        Box::new(move || AccumulatorWrapper::Expression {
1662                            evaluator: Rc::clone(&evaluator),
1663                            accumulator: Some(Box::new(CountAccumulator::default())),
1664                        })
1665                    }
1666                }
1667                AggregateFunction::Sum => {
1668                    let evaluator =
1669                        self.expression_evaluator(expr, encoded_variables, stat_children);
1670                    if *distinct {
1671                        Box::new(move || AccumulatorWrapper::DistinctExpression {
1672                            evaluator: Rc::clone(&evaluator),
1673                            seen: FxHashSet::default(),
1674                            accumulator: Some(Box::new(SumAccumulator::default())),
1675                        })
1676                    } else {
1677                        Box::new(move || AccumulatorWrapper::Expression {
1678                            evaluator: Rc::clone(&evaluator),
1679                            accumulator: Some(Box::new(SumAccumulator::default())),
1680                        })
1681                    }
1682                }
1683                AggregateFunction::Min => {
1684                    let evaluator =
1685                        self.expression_evaluator(expr, encoded_variables, stat_children);
1686                    if *distinct {
1687                        Box::new(move || AccumulatorWrapper::DistinctExpression {
1688                            evaluator: Rc::clone(&evaluator),
1689                            seen: FxHashSet::default(),
1690                            accumulator: Some(Box::new(MinAccumulator::default())),
1691                        })
1692                    } else {
1693                        Box::new(move || AccumulatorWrapper::Expression {
1694                            evaluator: Rc::clone(&evaluator),
1695                            accumulator: Some(Box::new(MinAccumulator::default())),
1696                        })
1697                    }
1698                }
1699                AggregateFunction::Max => {
1700                    let evaluator =
1701                        self.expression_evaluator(expr, encoded_variables, stat_children);
1702                    if *distinct {
1703                        Box::new(move || AccumulatorWrapper::DistinctExpression {
1704                            evaluator: Rc::clone(&evaluator),
1705                            seen: FxHashSet::default(),
1706                            accumulator: Some(Box::new(MaxAccumulator::default())),
1707                        })
1708                    } else {
1709                        Box::new(move || AccumulatorWrapper::Expression {
1710                            evaluator: Rc::clone(&evaluator),
1711                            accumulator: Some(Box::new(MaxAccumulator::default())),
1712                        })
1713                    }
1714                }
1715                AggregateFunction::Avg => {
1716                    let evaluator =
1717                        self.expression_evaluator(expr, encoded_variables, stat_children);
1718                    if *distinct {
1719                        Box::new(move || AccumulatorWrapper::DistinctExpression {
1720                            evaluator: Rc::clone(&evaluator),
1721                            seen: FxHashSet::default(),
1722                            accumulator: Some(Box::new(AvgAccumulator::default())),
1723                        })
1724                    } else {
1725                        Box::new(move || AccumulatorWrapper::Expression {
1726                            evaluator: Rc::clone(&evaluator),
1727                            accumulator: Some(Box::new(AvgAccumulator::default())),
1728                        })
1729                    }
1730                }
1731                AggregateFunction::Sample => {
1732                    let evaluator =
1733                        self.expression_evaluator(expr, encoded_variables, stat_children);
1734                    Box::new(move || AccumulatorWrapper::Sample {
1735                        evaluator: Rc::clone(&evaluator),
1736                        value: None,
1737                    })
1738                }
1739                AggregateFunction::GroupConcat { separator } => {
1740                    let separator = Rc::from(separator.as_deref().unwrap_or(" "));
1741                    let evaluator =
1742                        self.expression_evaluator(expr, encoded_variables, stat_children);
1743                    if *distinct {
1744                        Box::new(move || AccumulatorWrapper::DistinctExpression {
1745                            evaluator: Rc::clone(&evaluator),
1746                            seen: FxHashSet::default(),
1747                            accumulator: Some(Box::new(GroupConcatAccumulator::new(Rc::clone(
1748                                &separator,
1749                            )))),
1750                        })
1751                    } else {
1752                        Box::new(move || AccumulatorWrapper::Expression {
1753                            evaluator: Rc::clone(&evaluator),
1754                            accumulator: Some(Box::new(GroupConcatAccumulator::new(Rc::clone(
1755                                &separator,
1756                            )))),
1757                        })
1758                    }
1759                }
1760                AggregateFunction::Custom(_) => Box::new(move || AccumulatorWrapper::Failing),
1761            },
1762        }
1763    }
1764
1765    /// Evaluates an expression and returns an internal term
1766    ///
1767    /// Returns None if building such expression would mean to convert back to an internal term at the end.
1768    fn internal_expression_evaluator(
1769        &self,
1770        expression: &Expression,
1771        encoded_variables: &mut Vec<Variable>,
1772        stat_children: &mut Vec<Rc<EvalNodeWithStats>>,
1773    ) -> Option<Rc<dyn Fn(&InternalTuple<D>) -> Option<D::InternalTerm>>> {
1774        Some(match expression {
1775            Expression::NamedNode(t) => {
1776                let t = self.encode_term(t.clone()).ok();
1777                Rc::new(move |_| t.clone())
1778            }
1779            Expression::Literal(t) => {
1780                let t = self.encode_term(t.clone()).ok();
1781                Rc::new(move |_| t.clone())
1782            }
1783            Expression::Variable(v) => {
1784                let v = encode_variable(encoded_variables, v);
1785                Rc::new(move |tuple| tuple.get(v).cloned())
1786            }
1787            Expression::Coalesce(l) => {
1788                let l = l
1789                    .iter()
1790                    .map(|e| {
1791                        self.internal_expression_evaluator(e, encoded_variables, stat_children)
1792                    })
1793                    .collect::<Option<Vec<_>>>()?;
1794                Rc::new(move |tuple| {
1795                    for e in &l {
1796                        if let Some(result) = e(tuple) {
1797                            return Some(result);
1798                        }
1799                    }
1800                    None
1801                })
1802            }
1803            Expression::If(a, b, c) => {
1804                let a = self.effective_boolean_value_expression_evaluator(
1805                    a,
1806                    encoded_variables,
1807                    stat_children,
1808                );
1809                let b = self.internal_expression_evaluator(b, encoded_variables, stat_children)?;
1810                let c = self.internal_expression_evaluator(c, encoded_variables, stat_children)?;
1811                Rc::new(move |tuple| if a(tuple)? { b(tuple) } else { c(tuple) })
1812            }
1813            Expression::Or(_)
1814            | Expression::And(_)
1815            | Expression::Equal(_, _)
1816            | Expression::SameTerm(_, _)
1817            | Expression::Greater(_, _)
1818            | Expression::GreaterOrEqual(_, _)
1819            | Expression::Less(_, _)
1820            | Expression::LessOrEqual(_, _)
1821            | Expression::Add(_, _)
1822            | Expression::Subtract(_, _)
1823            | Expression::Multiply(_, _)
1824            | Expression::Divide(_, _)
1825            | Expression::UnaryPlus(_)
1826            | Expression::UnaryMinus(_)
1827            | Expression::Not(_)
1828            | Expression::Exists(_)
1829            | Expression::Bound(_)
1830            | Expression::FunctionCall(_, _) => return None, // TODO: we can do some functions
1831        })
1832    }
1833
1834    /// Evaluate an expression and return its effective boolean value
1835    fn effective_boolean_value_expression_evaluator(
1836        &self,
1837        expression: &Expression,
1838        encoded_variables: &mut Vec<Variable>,
1839        stat_children: &mut Vec<Rc<EvalNodeWithStats>>,
1840    ) -> Rc<dyn Fn(&InternalTuple<D>) -> Option<bool>> {
1841        // TODO: avoid dyn?
1842        if let Some(eval) =
1843            self.internal_expression_evaluator(expression, encoded_variables, stat_children)
1844        {
1845            let dataset = self.dataset.clone();
1846            return Rc::new(move |tuple| {
1847                dataset
1848                    .internal_term_effective_boolean_value(eval(tuple)?)
1849                    .ok()?
1850            });
1851        }
1852        let eval = self.expression_evaluator(expression, encoded_variables, stat_children);
1853        Rc::new(move |tuple| eval(tuple)?.effective_boolean_value())
1854    }
1855
1856    /// Evaluate an expression and return an explicit ExpressionTerm
1857    fn expression_evaluator(
1858        &self,
1859        expression: &Expression,
1860        encoded_variables: &mut Vec<Variable>,
1861        stat_children: &mut Vec<Rc<EvalNodeWithStats>>,
1862    ) -> Rc<dyn Fn(&InternalTuple<D>) -> Option<ExpressionTerm>> {
1863        match expression {
1864            Expression::NamedNode(t) => {
1865                let t = ExpressionTerm::from(Term::from(t.clone()));
1866                Rc::new(move |_| Some(t.clone()))
1867            }
1868            Expression::Literal(t) => {
1869                let t = ExpressionTerm::from(Term::from(t.clone()));
1870                Rc::new(move |_| Some(t.clone()))
1871            }
1872            Expression::Variable(v) => {
1873                let v = encode_variable(encoded_variables, v);
1874                let dataset = self.dataset.clone();
1875                Rc::new(move |tuple| {
1876                    tuple
1877                        .get(v)
1878                        .cloned()
1879                        .and_then(|t| dataset.externalize_expression_term(t).ok())
1880                })
1881            }
1882            Expression::Bound(v) => {
1883                let v = encode_variable(encoded_variables, v);
1884                Rc::new(move |tuple| Some(tuple.contains(v).into()))
1885            }
1886            Expression::Exists(plan) => {
1887                let (eval, stats) = self.graph_pattern_evaluator(plan, encoded_variables);
1888                stat_children.push(stats);
1889                Rc::new(move |tuple| Some(eval(tuple.clone()).next().is_some().into()))
1890            }
1891            Expression::Or(inner) => {
1892                let children = inner
1893                    .iter()
1894                    .map(|i| {
1895                        self.effective_boolean_value_expression_evaluator(
1896                            i,
1897                            encoded_variables,
1898                            stat_children,
1899                        )
1900                    })
1901                    .collect::<Rc<[_]>>();
1902                Rc::new(move |tuple| {
1903                    let mut error = false;
1904                    for child in &*children {
1905                        match child(tuple) {
1906                            Some(true) => return Some(true.into()),
1907                            Some(false) => (),
1908                            None => error = true,
1909                        }
1910                    }
1911                    if error {
1912                        None
1913                    } else {
1914                        Some(false.into())
1915                    }
1916                })
1917            }
1918            Expression::And(inner) => {
1919                let children = inner
1920                    .iter()
1921                    .map(|i| {
1922                        self.effective_boolean_value_expression_evaluator(
1923                            i,
1924                            encoded_variables,
1925                            stat_children,
1926                        )
1927                    })
1928                    .collect::<Rc<[_]>>();
1929                Rc::new(move |tuple| {
1930                    let mut error = false;
1931                    for child in &*children {
1932                        match child(tuple) {
1933                            Some(true) => (),
1934                            Some(false) => return Some(false.into()),
1935                            None => error = true,
1936                        }
1937                    }
1938                    if error {
1939                        None
1940                    } else {
1941                        Some(true.into())
1942                    }
1943                })
1944            }
1945            Expression::Equal(a, b) => {
1946                let a = self.expression_evaluator(a, encoded_variables, stat_children);
1947                let b = self.expression_evaluator(b, encoded_variables, stat_children);
1948                Rc::new(move |tuple| equals(&a(tuple)?, &b(tuple)?).map(Into::into))
1949            }
1950            Expression::SameTerm(a, b) => {
1951                if let (Some(a), Some(b)) = (
1952                    self.internal_expression_evaluator(a, encoded_variables, stat_children),
1953                    self.internal_expression_evaluator(b, encoded_variables, stat_children),
1954                ) {
1955                    return Rc::new(move |tuple| Some((a(tuple)? == b(tuple)?).into()));
1956                };
1957                let a = self.expression_evaluator(a, encoded_variables, stat_children);
1958                let b = self.expression_evaluator(b, encoded_variables, stat_children);
1959                // TODO: if one is an internal term, this might be wrong in case we got checks like SameTerm(01, 1+0)
1960                Rc::new(move |tuple| Some((a(tuple)? == b(tuple)?).into()))
1961            }
1962            Expression::Greater(a, b) => {
1963                let a = self.expression_evaluator(a, encoded_variables, stat_children);
1964                let b = self.expression_evaluator(b, encoded_variables, stat_children);
1965                Rc::new(move |tuple| {
1966                    Some((partial_cmp(&a(tuple)?, &b(tuple)?)? == Ordering::Greater).into())
1967                })
1968            }
1969            Expression::GreaterOrEqual(a, b) => {
1970                let a = self.expression_evaluator(a, encoded_variables, stat_children);
1971                let b = self.expression_evaluator(b, encoded_variables, stat_children);
1972                Rc::new(move |tuple| {
1973                    Some(
1974                        match partial_cmp(&a(tuple)?, &b(tuple)?)? {
1975                            Ordering::Greater | Ordering::Equal => true,
1976                            Ordering::Less => false,
1977                        }
1978                        .into(),
1979                    )
1980                })
1981            }
1982            Expression::Less(a, b) => {
1983                let a = self.expression_evaluator(a, encoded_variables, stat_children);
1984                let b = self.expression_evaluator(b, encoded_variables, stat_children);
1985                Rc::new(move |tuple| {
1986                    Some((partial_cmp(&a(tuple)?, &b(tuple)?)? == Ordering::Less).into())
1987                })
1988            }
1989            Expression::LessOrEqual(a, b) => {
1990                let a = self.expression_evaluator(a, encoded_variables, stat_children);
1991                let b = self.expression_evaluator(b, encoded_variables, stat_children);
1992                Rc::new(move |tuple| {
1993                    Some(
1994                        match partial_cmp(&a(tuple)?, &b(tuple)?)? {
1995                            Ordering::Less | Ordering::Equal => true,
1996                            Ordering::Greater => false,
1997                        }
1998                        .into(),
1999                    )
2000                })
2001            }
2002            Expression::Add(a, b) => {
2003                let a = self.expression_evaluator(a, encoded_variables, stat_children);
2004                let b = self.expression_evaluator(b, encoded_variables, stat_children);
2005                Rc::new(move |tuple| {
2006                    Some(match NumericBinaryOperands::new(a(tuple)?, b(tuple)?)? {
2007                        NumericBinaryOperands::Float(v1, v2) => {
2008                            ExpressionTerm::FloatLiteral(v1 + v2)
2009                        }
2010                        NumericBinaryOperands::Double(v1, v2) => {
2011                            ExpressionTerm::DoubleLiteral(v1 + v2)
2012                        }
2013                        NumericBinaryOperands::Integer(v1, v2) => {
2014                            ExpressionTerm::IntegerLiteral(v1.checked_add(v2)?)
2015                        }
2016                        NumericBinaryOperands::Decimal(v1, v2) => {
2017                            ExpressionTerm::DecimalLiteral(v1.checked_add(v2)?)
2018                        }
2019                        #[cfg(feature = "sep-0002")]
2020                        NumericBinaryOperands::Duration(v1, v2) => {
2021                            ExpressionTerm::DurationLiteral(v1.checked_add(v2)?)
2022                        }
2023                        #[cfg(feature = "sep-0002")]
2024                        NumericBinaryOperands::YearMonthDuration(v1, v2) => {
2025                            ExpressionTerm::YearMonthDurationLiteral(v1.checked_add(v2)?)
2026                        }
2027                        #[cfg(feature = "sep-0002")]
2028                        NumericBinaryOperands::DayTimeDuration(v1, v2) => {
2029                            ExpressionTerm::DayTimeDurationLiteral(v1.checked_add(v2)?)
2030                        }
2031                        #[cfg(feature = "sep-0002")]
2032                        NumericBinaryOperands::DateTimeDuration(v1, v2) => {
2033                            ExpressionTerm::DateTimeLiteral(v1.checked_add_duration(v2)?)
2034                        }
2035                        #[cfg(feature = "sep-0002")]
2036                        NumericBinaryOperands::DateTimeYearMonthDuration(v1, v2) => {
2037                            ExpressionTerm::DateTimeLiteral(v1.checked_add_year_month_duration(v2)?)
2038                        }
2039                        #[cfg(feature = "sep-0002")]
2040                        NumericBinaryOperands::DateTimeDayTimeDuration(v1, v2) => {
2041                            ExpressionTerm::DateTimeLiteral(v1.checked_add_day_time_duration(v2)?)
2042                        }
2043                        #[cfg(feature = "sep-0002")]
2044                        NumericBinaryOperands::DateDuration(v1, v2) => {
2045                            ExpressionTerm::DateLiteral(v1.checked_add_duration(v2)?)
2046                        }
2047                        #[cfg(feature = "sep-0002")]
2048                        NumericBinaryOperands::DateYearMonthDuration(v1, v2) => {
2049                            ExpressionTerm::DateLiteral(v1.checked_add_year_month_duration(v2)?)
2050                        }
2051                        #[cfg(feature = "sep-0002")]
2052                        NumericBinaryOperands::DateDayTimeDuration(v1, v2) => {
2053                            ExpressionTerm::DateLiteral(v1.checked_add_day_time_duration(v2)?)
2054                        }
2055                        #[cfg(feature = "sep-0002")]
2056                        NumericBinaryOperands::TimeDuration(v1, v2) => {
2057                            ExpressionTerm::TimeLiteral(v1.checked_add_duration(v2)?)
2058                        }
2059                        #[cfg(feature = "sep-0002")]
2060                        NumericBinaryOperands::TimeDayTimeDuration(v1, v2) => {
2061                            ExpressionTerm::TimeLiteral(v1.checked_add_day_time_duration(v2)?)
2062                        }
2063                        #[cfg(feature = "sep-0002")]
2064                        NumericBinaryOperands::DateTime(_, _)
2065                        | NumericBinaryOperands::Time(_, _)
2066                        | NumericBinaryOperands::Date(_, _) => return None,
2067                    })
2068                })
2069            }
2070            Expression::Subtract(a, b) => {
2071                let a = self.expression_evaluator(a, encoded_variables, stat_children);
2072                let b = self.expression_evaluator(b, encoded_variables, stat_children);
2073                Rc::new(move |tuple| {
2074                    Some(match NumericBinaryOperands::new(a(tuple)?, b(tuple)?)? {
2075                        NumericBinaryOperands::Float(v1, v2) => {
2076                            ExpressionTerm::FloatLiteral(v1 - v2)
2077                        }
2078                        NumericBinaryOperands::Double(v1, v2) => {
2079                            ExpressionTerm::DoubleLiteral(v1 - v2)
2080                        }
2081                        NumericBinaryOperands::Integer(v1, v2) => {
2082                            ExpressionTerm::IntegerLiteral(v1.checked_sub(v2)?)
2083                        }
2084                        NumericBinaryOperands::Decimal(v1, v2) => {
2085                            ExpressionTerm::DecimalLiteral(v1.checked_sub(v2)?)
2086                        }
2087                        #[cfg(feature = "sep-0002")]
2088                        NumericBinaryOperands::DateTime(v1, v2) => {
2089                            ExpressionTerm::DayTimeDurationLiteral(v1.checked_sub(v2)?)
2090                        }
2091                        #[cfg(feature = "sep-0002")]
2092                        NumericBinaryOperands::Date(v1, v2) => {
2093                            ExpressionTerm::DayTimeDurationLiteral(v1.checked_sub(v2)?)
2094                        }
2095                        #[cfg(feature = "sep-0002")]
2096                        NumericBinaryOperands::Time(v1, v2) => {
2097                            ExpressionTerm::DayTimeDurationLiteral(v1.checked_sub(v2)?)
2098                        }
2099                        #[cfg(feature = "sep-0002")]
2100                        NumericBinaryOperands::Duration(v1, v2) => {
2101                            ExpressionTerm::DurationLiteral(v1.checked_sub(v2)?)
2102                        }
2103                        #[cfg(feature = "sep-0002")]
2104                        NumericBinaryOperands::YearMonthDuration(v1, v2) => {
2105                            ExpressionTerm::YearMonthDurationLiteral(v1.checked_sub(v2)?)
2106                        }
2107                        #[cfg(feature = "sep-0002")]
2108                        NumericBinaryOperands::DayTimeDuration(v1, v2) => {
2109                            ExpressionTerm::DayTimeDurationLiteral(v1.checked_sub(v2)?)
2110                        }
2111                        #[cfg(feature = "sep-0002")]
2112                        NumericBinaryOperands::DateTimeDuration(v1, v2) => {
2113                            ExpressionTerm::DateTimeLiteral(v1.checked_sub_duration(v2)?)
2114                        }
2115                        #[cfg(feature = "sep-0002")]
2116                        NumericBinaryOperands::DateTimeYearMonthDuration(v1, v2) => {
2117                            ExpressionTerm::DateTimeLiteral(v1.checked_sub_year_month_duration(v2)?)
2118                        }
2119                        #[cfg(feature = "sep-0002")]
2120                        NumericBinaryOperands::DateTimeDayTimeDuration(v1, v2) => {
2121                            ExpressionTerm::DateTimeLiteral(v1.checked_sub_day_time_duration(v2)?)
2122                        }
2123                        #[cfg(feature = "sep-0002")]
2124                        NumericBinaryOperands::DateDuration(v1, v2) => {
2125                            ExpressionTerm::DateLiteral(v1.checked_sub_duration(v2)?)
2126                        }
2127                        #[cfg(feature = "sep-0002")]
2128                        NumericBinaryOperands::DateYearMonthDuration(v1, v2) => {
2129                            ExpressionTerm::DateLiteral(v1.checked_sub_year_month_duration(v2)?)
2130                        }
2131                        #[cfg(feature = "sep-0002")]
2132                        NumericBinaryOperands::DateDayTimeDuration(v1, v2) => {
2133                            ExpressionTerm::DateLiteral(v1.checked_sub_day_time_duration(v2)?)
2134                        }
2135                        #[cfg(feature = "sep-0002")]
2136                        NumericBinaryOperands::TimeDuration(v1, v2) => {
2137                            ExpressionTerm::TimeLiteral(v1.checked_sub_duration(v2)?)
2138                        }
2139                        #[cfg(feature = "sep-0002")]
2140                        NumericBinaryOperands::TimeDayTimeDuration(v1, v2) => {
2141                            ExpressionTerm::TimeLiteral(v1.checked_sub_day_time_duration(v2)?)
2142                        }
2143                    })
2144                })
2145            }
2146            Expression::Multiply(a, b) => {
2147                let a = self.expression_evaluator(a, encoded_variables, stat_children);
2148                let b = self.expression_evaluator(b, encoded_variables, stat_children);
2149                Rc::new(move |tuple| {
2150                    Some(match NumericBinaryOperands::new(a(tuple)?, b(tuple)?)? {
2151                        NumericBinaryOperands::Float(v1, v2) => {
2152                            ExpressionTerm::FloatLiteral(v1 * v2)
2153                        }
2154                        NumericBinaryOperands::Double(v1, v2) => {
2155                            ExpressionTerm::DoubleLiteral(v1 * v2)
2156                        }
2157                        NumericBinaryOperands::Integer(v1, v2) => {
2158                            ExpressionTerm::IntegerLiteral(v1.checked_mul(v2)?)
2159                        }
2160                        NumericBinaryOperands::Decimal(v1, v2) => {
2161                            ExpressionTerm::DecimalLiteral(v1.checked_mul(v2)?)
2162                        }
2163                        #[cfg(feature = "sep-0002")]
2164                        _ => return None,
2165                    })
2166                })
2167            }
2168            Expression::Divide(a, b) => {
2169                let a = self.expression_evaluator(a, encoded_variables, stat_children);
2170                let b = self.expression_evaluator(b, encoded_variables, stat_children);
2171                Rc::new(move |tuple| {
2172                    Some(match NumericBinaryOperands::new(a(tuple)?, b(tuple)?)? {
2173                        NumericBinaryOperands::Float(v1, v2) => {
2174                            ExpressionTerm::FloatLiteral(v1 / v2)
2175                        }
2176                        NumericBinaryOperands::Double(v1, v2) => {
2177                            ExpressionTerm::DoubleLiteral(v1 / v2)
2178                        }
2179                        NumericBinaryOperands::Integer(v1, v2) => {
2180                            ExpressionTerm::DecimalLiteral(Decimal::from(v1).checked_div(v2)?)
2181                        }
2182                        NumericBinaryOperands::Decimal(v1, v2) => {
2183                            ExpressionTerm::DecimalLiteral(v1.checked_div(v2)?)
2184                        }
2185                        #[cfg(feature = "sep-0002")]
2186                        _ => return None,
2187                    })
2188                })
2189            }
2190            Expression::UnaryPlus(e) => {
2191                let e = self.expression_evaluator(e, encoded_variables, stat_children);
2192                Rc::new(move |tuple| {
2193                    Some(match e(tuple)? {
2194                        ExpressionTerm::FloatLiteral(value) => ExpressionTerm::FloatLiteral(value),
2195                        ExpressionTerm::DoubleLiteral(value) => {
2196                            ExpressionTerm::DoubleLiteral(value)
2197                        }
2198                        ExpressionTerm::IntegerLiteral(value) => {
2199                            ExpressionTerm::IntegerLiteral(value)
2200                        }
2201                        ExpressionTerm::DecimalLiteral(value) => {
2202                            ExpressionTerm::DecimalLiteral(value)
2203                        }
2204                        #[cfg(feature = "sep-0002")]
2205                        ExpressionTerm::DurationLiteral(value) => {
2206                            ExpressionTerm::DurationLiteral(value)
2207                        }
2208                        #[cfg(feature = "sep-0002")]
2209                        ExpressionTerm::YearMonthDurationLiteral(value) => {
2210                            ExpressionTerm::YearMonthDurationLiteral(value)
2211                        }
2212                        #[cfg(feature = "sep-0002")]
2213                        ExpressionTerm::DayTimeDurationLiteral(value) => {
2214                            ExpressionTerm::DayTimeDurationLiteral(value)
2215                        }
2216                        _ => return None,
2217                    })
2218                })
2219            }
2220            Expression::UnaryMinus(e) => {
2221                let e = self.expression_evaluator(e, encoded_variables, stat_children);
2222                Rc::new(move |tuple| {
2223                    Some(match e(tuple)? {
2224                        ExpressionTerm::FloatLiteral(value) => ExpressionTerm::FloatLiteral(-value),
2225                        ExpressionTerm::DoubleLiteral(value) => {
2226                            ExpressionTerm::DoubleLiteral(-value)
2227                        }
2228                        ExpressionTerm::IntegerLiteral(value) => {
2229                            ExpressionTerm::IntegerLiteral(value.checked_neg()?)
2230                        }
2231                        ExpressionTerm::DecimalLiteral(value) => {
2232                            ExpressionTerm::DecimalLiteral(value.checked_neg()?)
2233                        }
2234                        #[cfg(feature = "sep-0002")]
2235                        ExpressionTerm::DurationLiteral(value) => {
2236                            ExpressionTerm::DurationLiteral(value.checked_neg()?)
2237                        }
2238                        #[cfg(feature = "sep-0002")]
2239                        ExpressionTerm::YearMonthDurationLiteral(value) => {
2240                            ExpressionTerm::YearMonthDurationLiteral(value.checked_neg()?)
2241                        }
2242                        #[cfg(feature = "sep-0002")]
2243                        ExpressionTerm::DayTimeDurationLiteral(value) => {
2244                            ExpressionTerm::DayTimeDurationLiteral(value.checked_neg()?)
2245                        }
2246                        _ => return None,
2247                    })
2248                })
2249            }
2250            Expression::Not(e) => {
2251                let e = self.effective_boolean_value_expression_evaluator(
2252                    e,
2253                    encoded_variables,
2254                    stat_children,
2255                );
2256                Rc::new(move |tuple| Some((!e(tuple)?).into()))
2257            }
2258            Expression::Coalesce(l) => {
2259                let l: Vec<_> = l
2260                    .iter()
2261                    .map(|e| self.expression_evaluator(e, encoded_variables, stat_children))
2262                    .collect();
2263                Rc::new(move |tuple| {
2264                    for e in &l {
2265                        if let Some(result) = e(tuple) {
2266                            return Some(result);
2267                        }
2268                    }
2269                    None
2270                })
2271            }
2272            Expression::If(a, b, c) => {
2273                let a = self.effective_boolean_value_expression_evaluator(
2274                    a,
2275                    encoded_variables,
2276                    stat_children,
2277                );
2278                let b = self.expression_evaluator(b, encoded_variables, stat_children);
2279                let c = self.expression_evaluator(c, encoded_variables, stat_children);
2280                Rc::new(move |tuple| if a(tuple)? { b(tuple) } else { c(tuple) })
2281            }
2282            Expression::FunctionCall(function, parameters) => match function {
2283                Function::Str => {
2284                    let e =
2285                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2286                    Rc::new(move |tuple| {
2287                        Some(ExpressionTerm::StringLiteral(match e(tuple)?.into() {
2288                            Term::NamedNode(term) => term.into_string(),
2289                            Term::BlankNode(_) => return None,
2290                            Term::Literal(term) => term.destruct().0,
2291                            #[cfg(feature = "rdf-star")]
2292                            Term::Triple(_) => return None,
2293                        }))
2294                    })
2295                }
2296                Function::Lang => {
2297                    let e =
2298                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2299                    Rc::new(move |tuple| {
2300                        Some(ExpressionTerm::StringLiteral(match e(tuple)? {
2301                            ExpressionTerm::LangStringLiteral { language, .. } => language,
2302                            ExpressionTerm::NamedNode(_) | ExpressionTerm::BlankNode(_) => {
2303                                return None
2304                            }
2305                            #[cfg(feature = "rdf-star")]
2306                            ExpressionTerm::Triple(_) => return None,
2307                            _ => String::new(),
2308                        }))
2309                    })
2310                }
2311                Function::LangMatches => {
2312                    let language_tag =
2313                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2314                    let language_range =
2315                        self.expression_evaluator(&parameters[1], encoded_variables, stat_children);
2316                    Rc::new(move |tuple| {
2317                        let ExpressionTerm::StringLiteral(mut language_tag) = language_tag(tuple)?
2318                        else {
2319                            return None;
2320                        };
2321                        language_tag.make_ascii_lowercase();
2322                        let ExpressionTerm::StringLiteral(mut language_range) =
2323                            language_range(tuple)?
2324                        else {
2325                            return None;
2326                        };
2327                        language_range.make_ascii_lowercase();
2328                        Some(
2329                            if &*language_range == "*" {
2330                                !language_tag.is_empty()
2331                            } else {
2332                                !ZipLongest::new(language_range.split('-'), language_tag.split('-'))
2333                                    .any(|parts| match parts {
2334                                        (Some(range_subtag), Some(language_subtag)) => {
2335                                            range_subtag != language_subtag
2336                                        }
2337                                        (Some(_), None) => true,
2338                                        (None, _) => false,
2339                                    })
2340                            }
2341                            .into(),
2342                        )
2343                    })
2344                }
2345                Function::Datatype => {
2346                    let e =
2347                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2348                    Rc::new(move |tuple| {
2349                        Some(ExpressionTerm::NamedNode(match e(tuple)? {
2350                            ExpressionTerm::StringLiteral(_) => xsd::STRING.into(),
2351                            ExpressionTerm::LangStringLiteral { .. } => rdf::LANG_STRING.into(),
2352                            ExpressionTerm::BooleanLiteral(_) => xsd::BOOLEAN.into(),
2353                            ExpressionTerm::IntegerLiteral(_) => xsd::INTEGER.into(),
2354                            ExpressionTerm::DecimalLiteral(_) => xsd::DECIMAL.into(),
2355                            ExpressionTerm::FloatLiteral(_) => xsd::FLOAT.into(),
2356                            ExpressionTerm::DoubleLiteral(_) => xsd::DOUBLE.into(),
2357                            ExpressionTerm::DateTimeLiteral(_) => xsd::DATE_TIME.into(),
2358                            #[cfg(feature = "sep-0002")]
2359                            ExpressionTerm::DateLiteral(_) => xsd::DATE.into(),
2360                            #[cfg(feature = "sep-0002")]
2361                            ExpressionTerm::TimeLiteral(_) => xsd::TIME.into(),
2362                            #[cfg(feature = "calendar-ext")]
2363                            ExpressionTerm::GYearLiteral(_) => xsd::G_YEAR.into(),
2364                            #[cfg(feature = "calendar-ext")]
2365                            ExpressionTerm::GYearMonthLiteral(_) => xsd::G_YEAR_MONTH.into(),
2366                            #[cfg(feature = "calendar-ext")]
2367                            ExpressionTerm::GMonthLiteral(_) => xsd::G_MONTH.into(),
2368                            #[cfg(feature = "calendar-ext")]
2369                            ExpressionTerm::GMonthDayLiteral(_) => xsd::G_MONTH_DAY.into(),
2370                            #[cfg(feature = "calendar-ext")]
2371                            ExpressionTerm::GDayLiteral(_) => xsd::G_DAY.into(),
2372                            #[cfg(feature = "sep-0002")]
2373                            ExpressionTerm::DurationLiteral(_) => xsd::DURATION.into(),
2374                            #[cfg(feature = "sep-0002")]
2375                            ExpressionTerm::YearMonthDurationLiteral(_) => {
2376                                xsd::YEAR_MONTH_DURATION.into()
2377                            }
2378                            #[cfg(feature = "sep-0002")]
2379                            ExpressionTerm::DayTimeDurationLiteral(_) => {
2380                                xsd::DAY_TIME_DURATION.into()
2381                            }
2382                            ExpressionTerm::OtherTypedLiteral { datatype, .. } => datatype,
2383                            ExpressionTerm::NamedNode(_) | ExpressionTerm::BlankNode(_) => {
2384                                return None
2385                            }
2386                            #[cfg(feature = "rdf-star")]
2387                            ExpressionTerm::Triple(_) => return None,
2388                        }))
2389                    })
2390                }
2391                Function::Iri => {
2392                    let e =
2393                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2394                    let base_iri = self.base_iri.clone();
2395                    Rc::new(move |tuple| {
2396                        Some(ExpressionTerm::NamedNode(match e(tuple)? {
2397                            ExpressionTerm::NamedNode(iri) => iri,
2398                            ExpressionTerm::StringLiteral(iri) => if let Some(base_iri) = &base_iri
2399                            {
2400                                base_iri.resolve(&iri)
2401                            } else {
2402                                Iri::parse(iri)
2403                            }
2404                            .ok()?
2405                            .into(),
2406                            _ => return None,
2407                        }))
2408                    })
2409                }
2410                Function::BNode => match parameters.first() {
2411                    Some(id) => {
2412                        let id = self.expression_evaluator(id, encoded_variables, stat_children);
2413                        Rc::new(move |tuple| {
2414                            let ExpressionTerm::StringLiteral(id) = id(tuple)? else {
2415                                return None;
2416                            };
2417                            Some(ExpressionTerm::BlankNode(BlankNode::new(id).ok()?))
2418                        })
2419                    }
2420                    None => Rc::new(|_| Some(ExpressionTerm::BlankNode(BlankNode::default()))),
2421                },
2422                Function::Rand => {
2423                    Rc::new(|_| Some(ExpressionTerm::DoubleLiteral(random::<f64>().into())))
2424                }
2425                Function::Abs => {
2426                    let e =
2427                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2428                    Rc::new(move |tuple| match e(tuple)? {
2429                        ExpressionTerm::IntegerLiteral(value) => {
2430                            Some(ExpressionTerm::IntegerLiteral(value.checked_abs()?))
2431                        }
2432                        ExpressionTerm::DecimalLiteral(value) => {
2433                            Some(ExpressionTerm::DecimalLiteral(value.checked_abs()?))
2434                        }
2435                        ExpressionTerm::FloatLiteral(value) => {
2436                            Some(ExpressionTerm::FloatLiteral(value.abs()))
2437                        }
2438                        ExpressionTerm::DoubleLiteral(value) => {
2439                            Some(ExpressionTerm::DoubleLiteral(value.abs()))
2440                        }
2441                        _ => None,
2442                    })
2443                }
2444                Function::Ceil => {
2445                    let e =
2446                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2447                    Rc::new(move |tuple| match e(tuple)? {
2448                        ExpressionTerm::IntegerLiteral(value) => {
2449                            Some(ExpressionTerm::IntegerLiteral(value))
2450                        }
2451                        ExpressionTerm::DecimalLiteral(value) => {
2452                            Some(ExpressionTerm::DecimalLiteral(value.checked_ceil()?))
2453                        }
2454                        ExpressionTerm::FloatLiteral(value) => {
2455                            Some(ExpressionTerm::FloatLiteral(value.ceil()))
2456                        }
2457                        ExpressionTerm::DoubleLiteral(value) => {
2458                            Some(ExpressionTerm::DoubleLiteral(value.ceil()))
2459                        }
2460                        _ => None,
2461                    })
2462                }
2463                Function::Floor => {
2464                    let e =
2465                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2466                    Rc::new(move |tuple| match e(tuple)? {
2467                        ExpressionTerm::IntegerLiteral(value) => {
2468                            Some(ExpressionTerm::IntegerLiteral(value))
2469                        }
2470                        ExpressionTerm::DecimalLiteral(value) => {
2471                            Some(ExpressionTerm::DecimalLiteral(value.checked_floor()?))
2472                        }
2473                        ExpressionTerm::FloatLiteral(value) => {
2474                            Some(ExpressionTerm::FloatLiteral(value.floor()))
2475                        }
2476                        ExpressionTerm::DoubleLiteral(value) => {
2477                            Some(ExpressionTerm::DoubleLiteral(value.floor()))
2478                        }
2479                        _ => None,
2480                    })
2481                }
2482                Function::Round => {
2483                    let e =
2484                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2485                    Rc::new(move |tuple| match e(tuple)? {
2486                        ExpressionTerm::IntegerLiteral(value) => {
2487                            Some(ExpressionTerm::IntegerLiteral(value))
2488                        }
2489                        ExpressionTerm::DecimalLiteral(value) => {
2490                            Some(ExpressionTerm::DecimalLiteral(value.checked_round()?))
2491                        }
2492                        ExpressionTerm::FloatLiteral(value) => {
2493                            Some(ExpressionTerm::FloatLiteral(value.round()))
2494                        }
2495                        ExpressionTerm::DoubleLiteral(value) => {
2496                            Some(ExpressionTerm::DoubleLiteral(value.round()))
2497                        }
2498                        _ => None,
2499                    })
2500                }
2501                Function::Concat => {
2502                    let l: Vec<_> = parameters
2503                        .iter()
2504                        .map(|e| self.expression_evaluator(e, encoded_variables, stat_children))
2505                        .collect();
2506                    Rc::new(move |tuple| {
2507                        let mut result = String::default();
2508                        let mut language = None;
2509                        for e in &l {
2510                            let (value, e_language) = to_string_and_language(e(tuple)?)?;
2511                            if let Some(lang) = &language {
2512                                if *lang != e_language {
2513                                    language = Some(None)
2514                                }
2515                            } else {
2516                                language = Some(e_language)
2517                            }
2518                            result += &value
2519                        }
2520                        Some(build_plain_literal(result, language.flatten()))
2521                    })
2522                }
2523                Function::SubStr => {
2524                    let source =
2525                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2526                    let starting_loc =
2527                        self.expression_evaluator(&parameters[1], encoded_variables, stat_children);
2528                    let length = parameters
2529                        .get(2)
2530                        .map(|l| self.expression_evaluator(l, encoded_variables, stat_children));
2531                    Rc::new(move |tuple| {
2532                        let (source, language) = to_string_and_language(source(tuple)?)?;
2533
2534                        let starting_location: usize =
2535                            if let ExpressionTerm::IntegerLiteral(v) = starting_loc(tuple)? {
2536                                usize::try_from(i64::from(v)).ok()?
2537                            } else {
2538                                return None;
2539                            };
2540                        let length = if let Some(length) = &length {
2541                            if let ExpressionTerm::IntegerLiteral(v) = length(tuple)? {
2542                                Some(usize::try_from(i64::from(v)).ok()?)
2543                            } else {
2544                                return None;
2545                            }
2546                        } else {
2547                            None
2548                        };
2549
2550                        // We want to slice on char indices, not byte indices
2551                        let mut start_iter = source
2552                            .char_indices()
2553                            .skip(starting_location.checked_sub(1)?)
2554                            .peekable();
2555                        let result = if let Some((start_position, _)) = start_iter.peek().copied() {
2556                            if let Some(length) = length {
2557                                let mut end_iter = start_iter.skip(length).peekable();
2558                                if let Some((end_position, _)) = end_iter.peek() {
2559                                    &source[start_position..*end_position]
2560                                } else {
2561                                    &source[start_position..]
2562                                }
2563                            } else {
2564                                &source[start_position..]
2565                            }
2566                        } else {
2567                            ""
2568                        };
2569                        Some(build_plain_literal(result.into(), language))
2570                    })
2571                }
2572                Function::StrLen => {
2573                    let arg =
2574                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2575                    Rc::new(move |tuple| {
2576                        let (string, _) = to_string_and_language(arg(tuple)?)?;
2577                        Some(ExpressionTerm::IntegerLiteral(
2578                            i64::try_from(string.chars().count()).ok()?.into(),
2579                        ))
2580                    })
2581                }
2582                Function::Replace => {
2583                    let arg =
2584                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2585                    let replacement =
2586                        self.expression_evaluator(&parameters[2], encoded_variables, stat_children);
2587                    if let Some(regex) =
2588                        compile_static_pattern_if_exists(&parameters[1], parameters.get(3))
2589                    {
2590                        Rc::new(move |tuple| {
2591                            let (text, language) = to_string_and_language(arg(tuple)?)?;
2592                            let ExpressionTerm::StringLiteral(replacement) = replacement(tuple)?
2593                            else {
2594                                return None;
2595                            };
2596                            Some(build_plain_literal(
2597                                match regex.replace_all(&text, &replacement) {
2598                                    Cow::Owned(replaced) => replaced,
2599                                    Cow::Borrowed(_) => text,
2600                                },
2601                                language,
2602                            ))
2603                        })
2604                    } else {
2605                        let pattern = self.expression_evaluator(
2606                            &parameters[1],
2607                            encoded_variables,
2608                            stat_children,
2609                        );
2610                        let flags = parameters.get(3).map(|flags| {
2611                            self.expression_evaluator(flags, encoded_variables, stat_children)
2612                        });
2613                        Rc::new(move |tuple| {
2614                            let ExpressionTerm::StringLiteral(pattern) = pattern(tuple)? else {
2615                                return None;
2616                            };
2617                            let options = if let Some(flags) = &flags {
2618                                let ExpressionTerm::StringLiteral(options) = flags(tuple)? else {
2619                                    return None;
2620                                };
2621                                Some(options)
2622                            } else {
2623                                None
2624                            };
2625                            let regex = compile_pattern(&pattern, options.as_deref())?;
2626                            let (text, language) = to_string_and_language(arg(tuple)?)?;
2627                            let ExpressionTerm::StringLiteral(replacement) = replacement(tuple)?
2628                            else {
2629                                return None;
2630                            };
2631                            Some(build_plain_literal(
2632                                match regex.replace_all(&text, &replacement) {
2633                                    Cow::Owned(replaced) => replaced,
2634                                    Cow::Borrowed(_) => text,
2635                                },
2636                                language,
2637                            ))
2638                        })
2639                    }
2640                }
2641                Function::UCase => {
2642                    let e =
2643                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2644                    Rc::new(move |tuple| {
2645                        let (value, language) = to_string_and_language(e(tuple)?)?;
2646                        Some(build_plain_literal(value.to_uppercase(), language))
2647                    })
2648                }
2649                Function::LCase => {
2650                    let e =
2651                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2652                    Rc::new(move |tuple| {
2653                        let (value, language) = to_string_and_language(e(tuple)?)?;
2654                        Some(build_plain_literal(value.to_lowercase(), language))
2655                    })
2656                }
2657                Function::StrStarts => {
2658                    let arg1 =
2659                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2660                    let arg2 =
2661                        self.expression_evaluator(&parameters[1], encoded_variables, stat_children);
2662                    Rc::new(move |tuple| {
2663                        let (arg1, arg2, _) =
2664                            to_argument_compatible_strings(arg1(tuple)?, arg2(tuple)?)?;
2665                        Some(arg1.starts_with(arg2.as_str()).into())
2666                    })
2667                }
2668                Function::EncodeForUri => {
2669                    let ltrl =
2670                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2671                    Rc::new(move |tuple| {
2672                        let (ltlr, _) = to_string_and_language(ltrl(tuple)?)?;
2673                        let mut result = Vec::with_capacity(ltlr.len());
2674                        for c in ltlr.bytes() {
2675                            match c {
2676                                b'A'..=b'Z'
2677                                | b'a'..=b'z'
2678                                | b'0'..=b'9'
2679                                | b'-'
2680                                | b'_'
2681                                | b'.'
2682                                | b'~' => result.push(c),
2683                                _ => {
2684                                    result.push(b'%');
2685                                    let high = c / 16;
2686                                    let low = c % 16;
2687                                    result.push(if high < 10 {
2688                                        b'0' + high
2689                                    } else {
2690                                        b'A' + (high - 10)
2691                                    });
2692                                    result.push(if low < 10 {
2693                                        b'0' + low
2694                                    } else {
2695                                        b'A' + (low - 10)
2696                                    });
2697                                }
2698                            }
2699                        }
2700                        Some(ExpressionTerm::StringLiteral(
2701                            String::from_utf8(result).ok()?,
2702                        ))
2703                    })
2704                }
2705                Function::StrEnds => {
2706                    let arg1 =
2707                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2708                    let arg2 =
2709                        self.expression_evaluator(&parameters[1], encoded_variables, stat_children);
2710                    Rc::new(move |tuple| {
2711                        let (arg1, arg2, _) =
2712                            to_argument_compatible_strings(arg1(tuple)?, arg2(tuple)?)?;
2713                        Some(arg1.ends_with(arg2.as_str()).into())
2714                    })
2715                }
2716                Function::Contains => {
2717                    let arg1 =
2718                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2719                    let arg2 =
2720                        self.expression_evaluator(&parameters[1], encoded_variables, stat_children);
2721                    Rc::new(move |tuple| {
2722                        let (arg1, arg2, _) =
2723                            to_argument_compatible_strings(arg1(tuple)?, arg2(tuple)?)?;
2724                        Some(arg1.contains(arg2.as_str()).into())
2725                    })
2726                }
2727                Function::StrBefore => {
2728                    let arg1 =
2729                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2730                    let arg2 =
2731                        self.expression_evaluator(&parameters[1], encoded_variables, stat_children);
2732                    Rc::new(move |tuple| {
2733                        let (arg1, arg2, language) =
2734                            to_argument_compatible_strings(arg1(tuple)?, arg2(tuple)?)?;
2735                        Some(if let Some(position) = arg1.find(arg2.as_str()) {
2736                            build_plain_literal(arg1[..position].into(), language)
2737                        } else {
2738                            ExpressionTerm::StringLiteral(String::new())
2739                        })
2740                    })
2741                }
2742                Function::StrAfter => {
2743                    let arg1 =
2744                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2745                    let arg2 =
2746                        self.expression_evaluator(&parameters[1], encoded_variables, stat_children);
2747                    Rc::new(move |tuple| {
2748                        let (arg1, arg2, language) =
2749                            to_argument_compatible_strings(arg1(tuple)?, arg2(tuple)?)?;
2750                        Some(if let Some(position) = arg1.find(arg2.as_str()) {
2751                            build_plain_literal(arg1[position + arg2.len()..].into(), language)
2752                        } else {
2753                            ExpressionTerm::StringLiteral(String::new())
2754                        })
2755                    })
2756                }
2757                Function::Year => {
2758                    let e =
2759                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2760                    Rc::new(move |tuple| {
2761                        Some(ExpressionTerm::IntegerLiteral(
2762                            match e(tuple)? {
2763                                ExpressionTerm::DateTimeLiteral(date_time) => date_time.year(),
2764                                #[cfg(feature = "sep-0002")]
2765                                ExpressionTerm::DateLiteral(date) => date.year(),
2766                                #[cfg(feature = "calendar-ext")]
2767                                ExpressionTerm::GYearMonthLiteral(year_month) => year_month.year(),
2768                                #[cfg(feature = "calendar-ext")]
2769                                ExpressionTerm::GYearLiteral(year) => year.year(),
2770                                _ => return None,
2771                            }
2772                            .into(),
2773                        ))
2774                    })
2775                }
2776                Function::Month => {
2777                    let e =
2778                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2779                    Rc::new(move |tuple| {
2780                        Some(ExpressionTerm::IntegerLiteral(
2781                            match e(tuple)? {
2782                                ExpressionTerm::DateTimeLiteral(date_time) => date_time.month(),
2783                                #[cfg(feature = "sep-0002")]
2784                                ExpressionTerm::DateLiteral(date) => date.month(),
2785                                #[cfg(feature = "calendar-ext")]
2786                                ExpressionTerm::GYearMonthLiteral(year_month) => year_month.month(),
2787                                #[cfg(feature = "calendar-ext")]
2788                                ExpressionTerm::GMonthDayLiteral(month_day) => month_day.month(),
2789                                #[cfg(feature = "calendar-ext")]
2790                                ExpressionTerm::GMonthLiteral(month) => month.month(),
2791                                _ => return None,
2792                            }
2793                            .into(),
2794                        ))
2795                    })
2796                }
2797                Function::Day => {
2798                    let e =
2799                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2800                    Rc::new(move |tuple| {
2801                        Some(ExpressionTerm::IntegerLiteral(
2802                            match e(tuple)? {
2803                                ExpressionTerm::DateTimeLiteral(date_time) => date_time.day(),
2804                                #[cfg(feature = "sep-0002")]
2805                                ExpressionTerm::DateLiteral(date) => date.day(),
2806                                #[cfg(feature = "calendar-ext")]
2807                                ExpressionTerm::GMonthDayLiteral(month_day) => month_day.day(),
2808                                #[cfg(feature = "calendar-ext")]
2809                                ExpressionTerm::GDayLiteral(day) => day.day(),
2810                                _ => return None,
2811                            }
2812                            .into(),
2813                        ))
2814                    })
2815                }
2816                Function::Hours => {
2817                    let e =
2818                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2819                    Rc::new(move |tuple| {
2820                        Some(ExpressionTerm::IntegerLiteral(
2821                            match e(tuple)? {
2822                                ExpressionTerm::DateTimeLiteral(date_time) => date_time.hour(),
2823                                #[cfg(feature = "sep-0002")]
2824                                ExpressionTerm::TimeLiteral(time) => time.hour(),
2825                                _ => return None,
2826                            }
2827                            .into(),
2828                        ))
2829                    })
2830                }
2831                Function::Minutes => {
2832                    let e =
2833                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2834                    Rc::new(move |tuple| {
2835                        Some(ExpressionTerm::IntegerLiteral(
2836                            match e(tuple)? {
2837                                ExpressionTerm::DateTimeLiteral(date_time) => date_time.minute(),
2838                                #[cfg(feature = "sep-0002")]
2839                                ExpressionTerm::TimeLiteral(time) => time.minute(),
2840                                _ => return None,
2841                            }
2842                            .into(),
2843                        ))
2844                    })
2845                }
2846                Function::Seconds => {
2847                    let e =
2848                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2849                    Rc::new(move |tuple| {
2850                        Some(ExpressionTerm::DecimalLiteral(match e(tuple)? {
2851                            ExpressionTerm::DateTimeLiteral(date_time) => date_time.second(),
2852                            #[cfg(feature = "sep-0002")]
2853                            ExpressionTerm::TimeLiteral(time) => time.second(),
2854                            _ => return None,
2855                        }))
2856                    })
2857                }
2858                Function::Timezone => {
2859                    let e =
2860                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2861                    Rc::new(move |tuple| {
2862                        let result = match e(tuple)? {
2863                            ExpressionTerm::DateTimeLiteral(date_time) => date_time.timezone(),
2864                            #[cfg(feature = "sep-0002")]
2865                            ExpressionTerm::TimeLiteral(time) => time.timezone(),
2866                            #[cfg(feature = "sep-0002")]
2867                            ExpressionTerm::DateLiteral(date) => date.timezone(),
2868                            #[cfg(feature = "calendar-ext")]
2869                            ExpressionTerm::GYearMonthLiteral(year_month) => year_month.timezone(),
2870                            #[cfg(feature = "calendar-ext")]
2871                            ExpressionTerm::GYearLiteral(year) => year.timezone(),
2872                            #[cfg(feature = "calendar-ext")]
2873                            ExpressionTerm::GMonthDayLiteral(month_day) => month_day.timezone(),
2874                            #[cfg(feature = "calendar-ext")]
2875                            ExpressionTerm::GDayLiteral(day) => day.timezone(),
2876                            #[cfg(feature = "calendar-ext")]
2877                            ExpressionTerm::GMonthLiteral(month) => month.timezone(),
2878                            _ => None,
2879                        }?;
2880                        #[cfg(feature = "sep-0002")]
2881                        {
2882                            Some(ExpressionTerm::DayTimeDurationLiteral(result))
2883                        }
2884                        #[cfg(not(feature = "sep-0002"))]
2885                        {
2886                            Some(ExpressionTerm::OtherTypedLiteral {
2887                                value: result.to_string(),
2888                                datatype: xsd::DAY_TIME_DURATION.into(),
2889                            })
2890                        }
2891                    })
2892                }
2893                Function::Tz => {
2894                    let e =
2895                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2896                    Rc::new(move |tuple| {
2897                        let timezone_offset = match e(tuple)? {
2898                            ExpressionTerm::DateTimeLiteral(date_time) => {
2899                                date_time.timezone_offset()
2900                            }
2901                            #[cfg(feature = "sep-0002")]
2902                            ExpressionTerm::TimeLiteral(time) => time.timezone_offset(),
2903                            #[cfg(feature = "sep-0002")]
2904                            ExpressionTerm::DateLiteral(date) => date.timezone_offset(),
2905                            #[cfg(feature = "calendar-ext")]
2906                            ExpressionTerm::GYearMonthLiteral(year_month) => {
2907                                year_month.timezone_offset()
2908                            }
2909                            #[cfg(feature = "calendar-ext")]
2910                            ExpressionTerm::GYearLiteral(year) => year.timezone_offset(),
2911                            #[cfg(feature = "calendar-ext")]
2912                            ExpressionTerm::GMonthDayLiteral(month_day) => {
2913                                month_day.timezone_offset()
2914                            }
2915                            #[cfg(feature = "calendar-ext")]
2916                            ExpressionTerm::GDayLiteral(day) => day.timezone_offset(),
2917                            #[cfg(feature = "calendar-ext")]
2918                            ExpressionTerm::GMonthLiteral(month) => month.timezone_offset(),
2919                            _ => return None,
2920                        };
2921                        Some(ExpressionTerm::StringLiteral(
2922                            timezone_offset.map_or_else(String::new, |o| o.to_string()),
2923                        ))
2924                    })
2925                }
2926                #[cfg(feature = "sep-0002")]
2927                Function::Adjust => {
2928                    let dt =
2929                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
2930                    let tz =
2931                        self.expression_evaluator(&parameters[1], encoded_variables, stat_children);
2932                    Rc::new(move |tuple| {
2933                        let timezone_offset = Some(
2934                            match tz(tuple)? {
2935                                ExpressionTerm::DayTimeDurationLiteral(tz) => {
2936                                    TimezoneOffset::try_from(tz)
2937                                }
2938                                ExpressionTerm::DurationLiteral(tz) => TimezoneOffset::try_from(tz),
2939                                _ => return None,
2940                            }
2941                            .ok()?,
2942                        );
2943                        Some(match dt(tuple)? {
2944                            ExpressionTerm::DateTimeLiteral(date_time) => {
2945                                ExpressionTerm::DateTimeLiteral(date_time.adjust(timezone_offset)?)
2946                            }
2947                            ExpressionTerm::TimeLiteral(time) => {
2948                                ExpressionTerm::TimeLiteral(time.adjust(timezone_offset)?)
2949                            }
2950                            ExpressionTerm::DateLiteral(date) => {
2951                                ExpressionTerm::DateLiteral(date.adjust(timezone_offset)?)
2952                            }
2953                            #[cfg(feature = "calendar-ext")]
2954                            ExpressionTerm::GYearMonthLiteral(year_month) => {
2955                                ExpressionTerm::GYearMonthLiteral(
2956                                    year_month.adjust(timezone_offset)?,
2957                                )
2958                            }
2959                            #[cfg(feature = "calendar-ext")]
2960                            ExpressionTerm::GYearLiteral(year) => {
2961                                ExpressionTerm::GYearLiteral(year.adjust(timezone_offset)?)
2962                            }
2963                            #[cfg(feature = "calendar-ext")]
2964                            ExpressionTerm::GMonthDayLiteral(month_day) => {
2965                                ExpressionTerm::GMonthDayLiteral(month_day.adjust(timezone_offset)?)
2966                            }
2967                            #[cfg(feature = "calendar-ext")]
2968                            ExpressionTerm::GDayLiteral(day) => {
2969                                ExpressionTerm::GDayLiteral(day.adjust(timezone_offset)?)
2970                            }
2971                            #[cfg(feature = "calendar-ext")]
2972                            ExpressionTerm::GMonthLiteral(month) => {
2973                                ExpressionTerm::GMonthLiteral(month.adjust(timezone_offset)?)
2974                            }
2975                            _ => return None,
2976                        })
2977                    })
2978                }
2979                Function::Now => {
2980                    let now = self.now;
2981                    Rc::new(move |_| Some(ExpressionTerm::DateTimeLiteral(now)))
2982                }
2983                Function::Uuid => Rc::new(move |_| {
2984                    let mut buffer = String::with_capacity(44);
2985                    buffer.push_str("urn:uuid:");
2986                    generate_uuid(&mut buffer);
2987                    Some(ExpressionTerm::NamedNode(NamedNode::new_unchecked(buffer)))
2988                }),
2989                Function::StrUuid => Rc::new(move |_| {
2990                    let mut buffer = String::with_capacity(36);
2991                    generate_uuid(&mut buffer);
2992                    Some(ExpressionTerm::StringLiteral(buffer))
2993                }),
2994                Function::Md5 => self.hash::<Md5>(parameters, encoded_variables, stat_children),
2995                Function::Sha1 => self.hash::<Sha1>(parameters, encoded_variables, stat_children),
2996                Function::Sha256 => {
2997                    self.hash::<Sha256>(parameters, encoded_variables, stat_children)
2998                }
2999                Function::Sha384 => {
3000                    self.hash::<Sha384>(parameters, encoded_variables, stat_children)
3001                }
3002                Function::Sha512 => {
3003                    self.hash::<Sha512>(parameters, encoded_variables, stat_children)
3004                }
3005                Function::StrLang => {
3006                    let lexical_form =
3007                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
3008                    let lang_tag =
3009                        self.expression_evaluator(&parameters[1], encoded_variables, stat_children);
3010                    Rc::new(move |tuple| {
3011                        let ExpressionTerm::StringLiteral(value) = lexical_form(tuple)? else {
3012                            return None;
3013                        };
3014                        let ExpressionTerm::StringLiteral(language) = lang_tag(tuple)? else {
3015                            return None;
3016                        };
3017                        Some(
3018                            Term::from(Literal::new_language_tagged_literal(value, language).ok()?)
3019                                .into(),
3020                        )
3021                    })
3022                }
3023                Function::StrDt => {
3024                    let lexical_form =
3025                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
3026                    let datatype =
3027                        self.expression_evaluator(&parameters[1], encoded_variables, stat_children);
3028                    Rc::new(move |tuple| {
3029                        let ExpressionTerm::StringLiteral(value) = lexical_form(tuple)? else {
3030                            return None;
3031                        };
3032                        let ExpressionTerm::NamedNode(datatype) = datatype(tuple)? else {
3033                            return None;
3034                        };
3035                        Some(Term::from(Literal::new_typed_literal(value, datatype)).into())
3036                    })
3037                }
3038
3039                Function::IsIri => {
3040                    let e =
3041                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
3042                    Rc::new(move |tuple| {
3043                        Some(matches!(e(tuple)?, ExpressionTerm::NamedNode(_)).into())
3044                    })
3045                }
3046                Function::IsBlank => {
3047                    let e =
3048                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
3049                    Rc::new(move |tuple| {
3050                        Some(matches!(e(tuple)?, ExpressionTerm::BlankNode(_)).into())
3051                    })
3052                }
3053                Function::IsLiteral => {
3054                    let e =
3055                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
3056                    Rc::new(move |tuple| {
3057                        Some(
3058                            match e(tuple)? {
3059                                ExpressionTerm::NamedNode(_) | ExpressionTerm::BlankNode(_) => {
3060                                    false
3061                                }
3062                                #[cfg(feature = "rdf-star")]
3063                                ExpressionTerm::Triple(_) => false,
3064                                _ => true,
3065                            }
3066                            .into(),
3067                        )
3068                    })
3069                }
3070                Function::IsNumeric => {
3071                    let e =
3072                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
3073                    Rc::new(move |tuple| {
3074                        Some(
3075                            matches!(
3076                                e(tuple)?,
3077                                ExpressionTerm::IntegerLiteral(_)
3078                                    | ExpressionTerm::DecimalLiteral(_)
3079                                    | ExpressionTerm::FloatLiteral(_)
3080                                    | ExpressionTerm::DoubleLiteral(_)
3081                            )
3082                            .into(),
3083                        )
3084                    })
3085                }
3086                Function::Regex => {
3087                    let text =
3088                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
3089                    if let Some(regex) =
3090                        compile_static_pattern_if_exists(&parameters[1], parameters.get(2))
3091                    {
3092                        Rc::new(move |tuple| {
3093                            let (text, _) = to_string_and_language(text(tuple)?)?;
3094                            Some(regex.is_match(&text).into())
3095                        })
3096                    } else {
3097                        let pattern = self.expression_evaluator(
3098                            &parameters[1],
3099                            encoded_variables,
3100                            stat_children,
3101                        );
3102                        let flags = parameters.get(2).map(|flags| {
3103                            self.expression_evaluator(flags, encoded_variables, stat_children)
3104                        });
3105                        Rc::new(move |tuple| {
3106                            let ExpressionTerm::StringLiteral(pattern) = pattern(tuple)? else {
3107                                return None;
3108                            };
3109                            let options = if let Some(flags) = &flags {
3110                                let ExpressionTerm::StringLiteral(options) = flags(tuple)? else {
3111                                    return None;
3112                                };
3113                                Some(options)
3114                            } else {
3115                                None
3116                            };
3117                            let regex = compile_pattern(&pattern, options.as_deref())?;
3118                            let (text, _) = to_string_and_language(text(tuple)?)?;
3119                            Some(regex.is_match(&text).into())
3120                        })
3121                    }
3122                }
3123                #[cfg(feature = "rdf-star")]
3124                Function::Triple => {
3125                    let s =
3126                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
3127                    let p =
3128                        self.expression_evaluator(&parameters[1], encoded_variables, stat_children);
3129                    let o =
3130                        self.expression_evaluator(&parameters[2], encoded_variables, stat_children);
3131                    Rc::new(move |tuple| {
3132                        Some(ExpressionTriple::new(s(tuple)?, p(tuple)?, o(tuple)?)?.into())
3133                    })
3134                }
3135                #[cfg(feature = "rdf-star")]
3136                Function::Subject => {
3137                    let e =
3138                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
3139                    Rc::new(move |tuple| {
3140                        if let ExpressionTerm::Triple(t) = e(tuple)? {
3141                            Some(t.subject.into())
3142                        } else {
3143                            None
3144                        }
3145                    })
3146                }
3147                #[cfg(feature = "rdf-star")]
3148                Function::Predicate => {
3149                    let e =
3150                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
3151                    Rc::new(move |tuple| {
3152                        if let ExpressionTerm::Triple(t) = e(tuple)? {
3153                            Some(t.predicate.into())
3154                        } else {
3155                            None
3156                        }
3157                    })
3158                }
3159                #[cfg(feature = "rdf-star")]
3160                Function::Object => {
3161                    let e =
3162                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
3163                    Rc::new(move |tuple| {
3164                        if let ExpressionTerm::Triple(t) = e(tuple)? {
3165                            Some(t.object)
3166                        } else {
3167                            None
3168                        }
3169                    })
3170                }
3171                #[cfg(feature = "rdf-star")]
3172                Function::IsTriple => {
3173                    let e =
3174                        self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
3175                    Rc::new(move |tuple| {
3176                        Some(matches!(e(tuple)?, ExpressionTerm::Triple(_)).into())
3177                    })
3178                }
3179                Function::Custom(function_name) => {
3180                    if let Some(function) = self.custom_functions.get(function_name).cloned() {
3181                        let args = parameters
3182                            .iter()
3183                            .map(|e| self.expression_evaluator(e, encoded_variables, stat_children))
3184                            .collect::<Vec<_>>();
3185                        return Rc::new(move |tuple| {
3186                            let args = args
3187                                .iter()
3188                                .map(|f| Some(f(tuple)?.into()))
3189                                .collect::<Option<Vec<Term>>>()?;
3190                            Some(function(&args)?.into())
3191                        });
3192                    }
3193                    match function_name.as_ref() {
3194                        xsd::STRING => {
3195                            let e = self.expression_evaluator(
3196                                &parameters[0],
3197                                encoded_variables,
3198                                stat_children,
3199                            );
3200                            Rc::new(move |tuple| {
3201                                Some(ExpressionTerm::StringLiteral(match e(tuple)?.into() {
3202                                    Term::NamedNode(term) => term.into_string(),
3203                                    Term::BlankNode(_) => return None,
3204                                    Term::Literal(term) => term.destruct().0,
3205                                    #[cfg(feature = "rdf-star")]
3206                                    Term::Triple(_) => return None,
3207                                }))
3208                            })
3209                        }
3210                        xsd::BOOLEAN => {
3211                            let e = self.expression_evaluator(
3212                                &parameters[0],
3213                                encoded_variables,
3214                                stat_children,
3215                            );
3216                            Rc::new(move |tuple| {
3217                                Some(ExpressionTerm::BooleanLiteral(match e(tuple)? {
3218                                    ExpressionTerm::BooleanLiteral(value) => value,
3219                                    ExpressionTerm::FloatLiteral(value) => value.into(),
3220                                    ExpressionTerm::DoubleLiteral(value) => value.into(),
3221                                    ExpressionTerm::IntegerLiteral(value) => value.into(),
3222                                    ExpressionTerm::DecimalLiteral(value) => value.into(),
3223                                    ExpressionTerm::StringLiteral(value) => value.parse().ok()?,
3224                                    _ => return None,
3225                                }))
3226                            })
3227                        }
3228                        xsd::DOUBLE => {
3229                            let e = self.expression_evaluator(
3230                                &parameters[0],
3231                                encoded_variables,
3232                                stat_children,
3233                            );
3234                            Rc::new(move |tuple| {
3235                                Some(ExpressionTerm::DoubleLiteral(match e(tuple)? {
3236                                    ExpressionTerm::FloatLiteral(value) => value.into(),
3237                                    ExpressionTerm::DoubleLiteral(value) => value,
3238                                    ExpressionTerm::IntegerLiteral(value) => value.into(),
3239                                    ExpressionTerm::DecimalLiteral(value) => value.into(),
3240                                    ExpressionTerm::BooleanLiteral(value) => value.into(),
3241                                    ExpressionTerm::StringLiteral(value) => value.parse().ok()?,
3242                                    _ => return None,
3243                                }))
3244                            })
3245                        }
3246                        xsd::FLOAT => {
3247                            let e = self.expression_evaluator(
3248                                &parameters[0],
3249                                encoded_variables,
3250                                stat_children,
3251                            );
3252                            Rc::new(move |tuple| {
3253                                Some(ExpressionTerm::FloatLiteral(match e(tuple)? {
3254                                    ExpressionTerm::FloatLiteral(value) => value,
3255                                    ExpressionTerm::DoubleLiteral(value) => value.into(),
3256                                    ExpressionTerm::IntegerLiteral(value) => value.into(),
3257                                    ExpressionTerm::DecimalLiteral(value) => value.into(),
3258                                    ExpressionTerm::BooleanLiteral(value) => value.into(),
3259                                    ExpressionTerm::StringLiteral(value) => value.parse().ok()?,
3260                                    _ => return None,
3261                                }))
3262                            })
3263                        }
3264                        xsd::INTEGER => {
3265                            let e = self.expression_evaluator(
3266                                &parameters[0],
3267                                encoded_variables,
3268                                stat_children,
3269                            );
3270                            Rc::new(move |tuple| {
3271                                Some(ExpressionTerm::IntegerLiteral(match e(tuple)? {
3272                                    ExpressionTerm::FloatLiteral(value) => value.try_into().ok()?,
3273                                    ExpressionTerm::DoubleLiteral(value) => {
3274                                        value.try_into().ok()?
3275                                    }
3276                                    ExpressionTerm::IntegerLiteral(value) => value,
3277                                    ExpressionTerm::DecimalLiteral(value) => {
3278                                        value.try_into().ok()?
3279                                    }
3280                                    ExpressionTerm::BooleanLiteral(value) => value.into(),
3281                                    ExpressionTerm::StringLiteral(value) => value.parse().ok()?,
3282                                    _ => return None,
3283                                }))
3284                            })
3285                        }
3286                        xsd::DECIMAL => {
3287                            let e = self.expression_evaluator(
3288                                &parameters[0],
3289                                encoded_variables,
3290                                stat_children,
3291                            );
3292                            Rc::new(move |tuple| {
3293                                Some(ExpressionTerm::DecimalLiteral(match e(tuple)? {
3294                                    ExpressionTerm::FloatLiteral(value) => value.try_into().ok()?,
3295                                    ExpressionTerm::DoubleLiteral(value) => {
3296                                        value.try_into().ok()?
3297                                    }
3298                                    ExpressionTerm::IntegerLiteral(value) => value.into(),
3299                                    ExpressionTerm::DecimalLiteral(value) => value,
3300                                    ExpressionTerm::BooleanLiteral(value) => value.into(),
3301                                    ExpressionTerm::StringLiteral(value) => value.parse().ok()?,
3302                                    _ => return None,
3303                                }))
3304                            })
3305                        }
3306                        #[cfg(feature = "sep-0002")]
3307                        xsd::DATE => {
3308                            let e = self.expression_evaluator(
3309                                &parameters[0],
3310                                encoded_variables,
3311                                stat_children,
3312                            );
3313                            Rc::new(move |tuple| {
3314                                Some(ExpressionTerm::DateLiteral(match e(tuple)? {
3315                                    ExpressionTerm::DateLiteral(value) => value,
3316                                    ExpressionTerm::DateTimeLiteral(value) => {
3317                                        value.try_into().ok()?
3318                                    }
3319                                    ExpressionTerm::StringLiteral(value) => value.parse().ok()?,
3320                                    _ => return None,
3321                                }))
3322                            })
3323                        }
3324                        #[cfg(feature = "sep-0002")]
3325                        xsd::TIME => {
3326                            let e = self.expression_evaluator(
3327                                &parameters[0],
3328                                encoded_variables,
3329                                stat_children,
3330                            );
3331                            Rc::new(move |tuple| {
3332                                Some(ExpressionTerm::TimeLiteral(match e(tuple)? {
3333                                    ExpressionTerm::TimeLiteral(value) => value,
3334                                    ExpressionTerm::DateTimeLiteral(value) => value.into(),
3335                                    ExpressionTerm::StringLiteral(value) => value.parse().ok()?,
3336                                    _ => return None,
3337                                }))
3338                            })
3339                        }
3340                        xsd::DATE_TIME => {
3341                            let e = self.expression_evaluator(
3342                                &parameters[0],
3343                                encoded_variables,
3344                                stat_children,
3345                            );
3346                            Rc::new(move |tuple| {
3347                                Some(ExpressionTerm::DateTimeLiteral(match e(tuple)? {
3348                                    ExpressionTerm::DateTimeLiteral(value) => value,
3349                                    #[cfg(feature = "sep-0002")]
3350                                    ExpressionTerm::DateLiteral(value) => value.try_into().ok()?,
3351                                    ExpressionTerm::StringLiteral(value) => value.parse().ok()?,
3352                                    _ => return None,
3353                                }))
3354                            })
3355                        }
3356                        #[cfg(feature = "sep-0002")]
3357                        xsd::DURATION => {
3358                            let e = self.expression_evaluator(
3359                                &parameters[0],
3360                                encoded_variables,
3361                                stat_children,
3362                            );
3363                            Rc::new(move |tuple| {
3364                                Some(ExpressionTerm::DurationLiteral(match e(tuple)? {
3365                                    ExpressionTerm::DurationLiteral(value) => value,
3366                                    ExpressionTerm::YearMonthDurationLiteral(value) => value.into(),
3367                                    ExpressionTerm::DayTimeDurationLiteral(value) => value.into(),
3368                                    ExpressionTerm::StringLiteral(value) => value.parse().ok()?,
3369                                    _ => return None,
3370                                }))
3371                            })
3372                        }
3373                        #[cfg(feature = "sep-0002")]
3374                        xsd::YEAR_MONTH_DURATION => {
3375                            let e = self.expression_evaluator(
3376                                &parameters[0],
3377                                encoded_variables,
3378                                stat_children,
3379                            );
3380                            Rc::new(move |tuple| {
3381                                Some(ExpressionTerm::YearMonthDurationLiteral(match e(tuple)? {
3382                                    ExpressionTerm::DurationLiteral(value) => {
3383                                        value.try_into().ok()?
3384                                    }
3385                                    ExpressionTerm::YearMonthDurationLiteral(value) => value,
3386                                    ExpressionTerm::StringLiteral(value) => value.parse().ok()?,
3387                                    _ => return None,
3388                                }))
3389                            })
3390                        }
3391                        #[cfg(feature = "sep-0002")]
3392                        xsd::DAY_TIME_DURATION => {
3393                            let e = self.expression_evaluator(
3394                                &parameters[0],
3395                                encoded_variables,
3396                                stat_children,
3397                            );
3398                            Rc::new(move |tuple| {
3399                                Some(ExpressionTerm::DayTimeDurationLiteral(match e(tuple)? {
3400                                    ExpressionTerm::DurationLiteral(value) => {
3401                                        value.try_into().ok()?
3402                                    }
3403                                    ExpressionTerm::DayTimeDurationLiteral(value) => value,
3404                                    ExpressionTerm::StringLiteral(value) => value.parse().ok()?,
3405                                    _ => return None,
3406                                }))
3407                            })
3408                        }
3409                        // TODO: gYear...
3410                        _ => Rc::new(|_| None),
3411                    }
3412                }
3413            },
3414        }
3415    }
3416
3417    fn hash<H: Digest>(
3418        &self,
3419        parameters: &[Expression],
3420        encoded_variables: &mut Vec<Variable>,
3421        stat_children: &mut Vec<Rc<EvalNodeWithStats>>,
3422    ) -> Rc<dyn Fn(&InternalTuple<D>) -> Option<ExpressionTerm>> {
3423        let arg = self.expression_evaluator(&parameters[0], encoded_variables, stat_children);
3424        Rc::new(move |tuple| {
3425            let ExpressionTerm::StringLiteral(input) = arg(tuple)? else {
3426                return None;
3427            };
3428            let hash = hex::encode(H::new().chain_update(input.as_str()).finalize());
3429            Some(ExpressionTerm::StringLiteral(hash))
3430        })
3431    }
3432
3433    fn encode_term(&self, term: impl Into<Term>) -> Result<D::InternalTerm, QueryEvaluationError> {
3434        self.dataset.internalize_term(term.into())
3435    }
3436
3437    #[cfg(feature = "rdf-star")]
3438    fn encode_triple(
3439        &self,
3440        triple: &GroundTriple,
3441    ) -> Result<D::InternalTerm, QueryEvaluationError> {
3442        self.dataset.internalize_expression_term(
3443            ExpressionTriple::from(Triple::from(triple.clone())).into(),
3444        )
3445    }
3446
3447    fn encode_property_path(
3448        &self,
3449        path: &PropertyPathExpression,
3450    ) -> Result<Rc<PropertyPath<D>>, QueryEvaluationError> {
3451        Ok(Rc::new(match path {
3452            PropertyPathExpression::NamedNode(node) => {
3453                PropertyPath::Path(self.encode_term(node.clone())?)
3454            }
3455            PropertyPathExpression::Reverse(p) => {
3456                PropertyPath::Reverse(self.encode_property_path(p)?)
3457            }
3458            PropertyPathExpression::Sequence(a, b) => {
3459                PropertyPath::Sequence(self.encode_property_path(a)?, self.encode_property_path(b)?)
3460            }
3461            PropertyPathExpression::Alternative(a, b) => PropertyPath::Alternative(
3462                self.encode_property_path(a)?,
3463                self.encode_property_path(b)?,
3464            ),
3465            PropertyPathExpression::ZeroOrMore(p) => {
3466                PropertyPath::ZeroOrMore(self.encode_property_path(p)?)
3467            }
3468            PropertyPathExpression::OneOrMore(p) => {
3469                PropertyPath::OneOrMore(self.encode_property_path(p)?)
3470            }
3471            PropertyPathExpression::ZeroOrOne(p) => {
3472                PropertyPath::ZeroOrOne(self.encode_property_path(p)?)
3473            }
3474            PropertyPathExpression::NegatedPropertySet(ps) => PropertyPath::NegatedPropertySet(
3475                ps.iter()
3476                    .map(|p| self.encode_term(p.clone()))
3477                    .collect::<Result<Rc<[_]>, _>>()?,
3478            ),
3479        }))
3480    }
3481}
3482
3483impl<D: QueryableDataset> Clone for SimpleEvaluator<D> {
3484    fn clone(&self) -> Self {
3485        Self {
3486            dataset: self.dataset.clone(),
3487            base_iri: self.base_iri.clone(),
3488            now: self.now,
3489            service_handler: Rc::clone(&self.service_handler),
3490            custom_functions: Rc::clone(&self.custom_functions),
3491            run_stats: self.run_stats,
3492        }
3493    }
3494}
3495
3496fn to_string_and_language(term: ExpressionTerm) -> Option<(String, Option<String>)> {
3497    match term {
3498        ExpressionTerm::StringLiteral(value) => Some((value, None)),
3499        ExpressionTerm::LangStringLiteral { value, language } => Some((value, Some(language))),
3500        _ => None,
3501    }
3502}
3503
3504fn build_plain_literal(value: String, language: Option<String>) -> ExpressionTerm {
3505    if let Some(language) = language {
3506        ExpressionTerm::LangStringLiteral { value, language }
3507    } else {
3508        ExpressionTerm::StringLiteral(value)
3509    }
3510}
3511
3512fn to_argument_compatible_strings(
3513    arg1: ExpressionTerm,
3514    arg2: ExpressionTerm,
3515) -> Option<(String, String, Option<String>)> {
3516    let (value1, language1) = to_string_and_language(arg1)?;
3517    let (value2, language2) = to_string_and_language(arg2)?;
3518    (language2.is_none() || language1 == language2).then_some((value1, value2, language1))
3519}
3520
3521fn compile_static_pattern_if_exists(
3522    pattern: &Expression,
3523    options: Option<&Expression>,
3524) -> Option<Regex> {
3525    let static_pattern = if let Expression::Literal(pattern) = pattern {
3526        (pattern.datatype() == xsd::STRING).then(|| pattern.value())
3527    } else {
3528        None
3529    };
3530    let static_options = if let Some(options) = options {
3531        if let Expression::Literal(options) = options {
3532            (options.datatype() == xsd::STRING).then(|| Some(options.value()))
3533        } else {
3534            None
3535        }
3536    } else {
3537        Some(None)
3538    };
3539    if let (Some(static_pattern), Some(static_options)) = (static_pattern, static_options) {
3540        compile_pattern(static_pattern, static_options)
3541    } else {
3542        None
3543    }
3544}
3545
3546fn compile_pattern(pattern: &str, flags: Option<&str>) -> Option<Regex> {
3547    let mut pattern = Cow::Borrowed(pattern);
3548    let flags = flags.unwrap_or_default();
3549    if flags.contains('q') {
3550        pattern = regex::escape(&pattern).into();
3551    }
3552    let mut regex_builder = RegexBuilder::new(&pattern);
3553    regex_builder.size_limit(REGEX_SIZE_LIMIT);
3554    for flag in flags.chars() {
3555        match flag {
3556            's' => {
3557                regex_builder.dot_matches_new_line(true);
3558            }
3559            'm' => {
3560                regex_builder.multi_line(true);
3561            }
3562            'i' => {
3563                regex_builder.case_insensitive(true);
3564            }
3565            'x' => {
3566                regex_builder.ignore_whitespace(true);
3567            }
3568            'q' => (),        // Already supported
3569            _ => return None, // invalid option
3570        }
3571    }
3572    regex_builder.build().ok()
3573}
3574
3575fn decode_bindings<D: QueryableDataset>(
3576    dataset: EvalDataset<D>,
3577    iter: InternalTuplesIterator<D>,
3578    variables: Arc<[Variable]>,
3579) -> QuerySolutionIter {
3580    let tuple_size = variables.len();
3581    QuerySolutionIter::new(
3582        Arc::clone(&variables),
3583        Box::new(iter.map(move |values| {
3584            let mut result = vec![None; tuple_size];
3585            for (i, value) in values?.iter().enumerate() {
3586                if let Some(term) = value {
3587                    result[i] = Some(dataset.externalize_term(term)?)
3588                }
3589            }
3590            Ok((Arc::clone(&variables), result).into())
3591        })),
3592    )
3593}
3594
3595// this is used to encode results from a BindingIterator into an InternalTuplesIterator. This happens when SERVICE clauses are evaluated
3596fn encode_bindings<D: QueryableDataset>(
3597    dataset: EvalDataset<D>,
3598    variables: Rc<[Variable]>,
3599    iter: QuerySolutionIter,
3600) -> InternalTuplesIterator<D> {
3601    Box::new(iter.map(move |solution| {
3602        let mut encoded_terms = InternalTuple::with_capacity(variables.len());
3603        for (variable, term) in &solution? {
3604            put_variable_value(
3605                variable,
3606                &variables,
3607                dataset.internalize_term(term.clone())?,
3608                &mut encoded_terms,
3609            );
3610        }
3611        Ok(encoded_terms)
3612    }))
3613}
3614
3615fn encode_initial_bindings<D: QueryableDataset>(
3616    dataset: &EvalDataset<D>,
3617    variables: &[Variable],
3618    values: impl IntoIterator<Item = (Variable, Term)>,
3619) -> Result<InternalTuple<D>, QueryEvaluationError> {
3620    let mut encoded_terms = InternalTuple::with_capacity(variables.len());
3621    for (variable, term) in values {
3622        if !put_variable_value(
3623            &variable,
3624            variables,
3625            dataset.internalize_term(term)?,
3626            &mut encoded_terms,
3627        ) {
3628            return Err(QueryEvaluationError::NotExistingSubstitutedVariable(
3629                variable,
3630            ));
3631        }
3632    }
3633    Ok(encoded_terms)
3634}
3635
3636fn put_variable_value<D: QueryableDataset>(
3637    selector: &Variable,
3638    variables: &[Variable],
3639    value: D::InternalTerm,
3640    tuple: &mut InternalTuple<D>,
3641) -> bool {
3642    for (i, v) in variables.iter().enumerate() {
3643        if selector == v {
3644            tuple.set(i, value);
3645            return true;
3646        }
3647    }
3648    false
3649}
3650
3651enum AccumulatorWrapper<D: QueryableDataset> {
3652    CountTuple {
3653        count: u64,
3654    },
3655    CountDistinctTuple {
3656        seen: FxHashSet<InternalTuple<D>>,
3657        count: u64,
3658    },
3659    CountInternal {
3660        evaluator: Rc<dyn Fn(&InternalTuple<D>) -> Option<D::InternalTerm>>,
3661        count: u64,
3662    },
3663    CountDistinctInternal {
3664        seen: FxHashSet<D::InternalTerm>,
3665        evaluator: Rc<dyn Fn(&InternalTuple<D>) -> Option<D::InternalTerm>>,
3666        count: u64,
3667    },
3668    Sample {
3669        // TODO: add internal variant
3670        evaluator: Rc<dyn Fn(&InternalTuple<D>) -> Option<ExpressionTerm>>,
3671        value: Option<ExpressionTerm>,
3672    },
3673    Expression {
3674        evaluator: Rc<dyn Fn(&InternalTuple<D>) -> Option<ExpressionTerm>>,
3675        accumulator: Option<Box<dyn Accumulator>>,
3676    },
3677    DistinctExpression {
3678        seen: FxHashSet<ExpressionTerm>,
3679        evaluator: Rc<dyn Fn(&InternalTuple<D>) -> Option<ExpressionTerm>>,
3680        accumulator: Option<Box<dyn Accumulator>>,
3681    },
3682    Failing,
3683}
3684
3685impl<D: QueryableDataset> AccumulatorWrapper<D> {
3686    fn add(&mut self, tuple: &InternalTuple<D>) {
3687        match self {
3688            Self::CountTuple { count } => {
3689                *count += 1;
3690            }
3691            Self::CountDistinctTuple { seen, count } => {
3692                if seen.insert(tuple.clone()) {
3693                    *count += 1;
3694                }
3695            }
3696            Self::CountInternal { evaluator, count } => {
3697                if evaluator(tuple).is_some() {
3698                    *count += 1;
3699                };
3700            }
3701            Self::CountDistinctInternal {
3702                seen,
3703                evaluator,
3704                count,
3705            } => {
3706                let Some(value) = evaluator(tuple) else {
3707                    return;
3708                };
3709                if seen.insert(value) {
3710                    *count += 1;
3711                }
3712            }
3713            Self::Sample { evaluator, value } => {
3714                if value.is_some() {
3715                    return; // We already got a value
3716                }
3717                *value = evaluator(tuple);
3718            }
3719            Self::Expression {
3720                evaluator,
3721                accumulator,
3722            } => {
3723                if accumulator.is_none() {
3724                    return; // Already failed
3725                }
3726                let Some(value) = evaluator(tuple) else {
3727                    *accumulator = None;
3728                    return;
3729                };
3730                let Some(accumulator) = accumulator else {
3731                    return;
3732                };
3733                accumulator.add(value);
3734            }
3735            Self::DistinctExpression {
3736                seen,
3737                evaluator,
3738                accumulator,
3739            } => {
3740                if accumulator.is_none() {
3741                    return; // Already failed
3742                }
3743                let Some(value) = evaluator(tuple) else {
3744                    *accumulator = None;
3745                    return;
3746                };
3747                let Some(accumulator) = accumulator else {
3748                    return;
3749                };
3750                if seen.insert(value.clone()) {
3751                    accumulator.add(value);
3752                }
3753            }
3754            Self::Failing => (),
3755        }
3756    }
3757
3758    fn finish(self) -> Option<ExpressionTerm> {
3759        match self {
3760            Self::CountTuple { count, .. }
3761            | Self::CountDistinctTuple { count, .. }
3762            | Self::CountInternal { count, .. }
3763            | Self::CountDistinctInternal { count, .. } => Some(ExpressionTerm::IntegerLiteral(
3764                i64::try_from(count).ok()?.into(),
3765            )),
3766            Self::Sample { value, .. } => value,
3767            Self::Expression { accumulator, .. } | Self::DistinctExpression { accumulator, .. } => {
3768                accumulator?.finish()
3769            }
3770            Self::Failing => None,
3771        }
3772    }
3773}
3774
3775trait Accumulator {
3776    fn add(&mut self, element: ExpressionTerm);
3777
3778    fn finish(&mut self) -> Option<ExpressionTerm>;
3779}
3780
3781#[derive(Default, Debug)]
3782struct CountAccumulator {
3783    count: i64,
3784}
3785
3786impl Accumulator for CountAccumulator {
3787    fn add(&mut self, _element: ExpressionTerm) {
3788        self.count += 1;
3789    }
3790
3791    fn finish(&mut self) -> Option<ExpressionTerm> {
3792        Some(ExpressionTerm::IntegerLiteral(self.count.into()))
3793    }
3794}
3795
3796struct SumAccumulator {
3797    sum: Option<ExpressionTerm>,
3798}
3799
3800impl Default for SumAccumulator {
3801    fn default() -> Self {
3802        Self {
3803            sum: Some(ExpressionTerm::IntegerLiteral(Integer::default())),
3804        }
3805    }
3806}
3807
3808impl Accumulator for SumAccumulator {
3809    fn add(&mut self, element: ExpressionTerm) {
3810        let Some(sum) = &self.sum else {
3811            return;
3812        };
3813        self.sum = if let Some(operands) = NumericBinaryOperands::new(sum.clone(), element) {
3814            // TODO: unify with addition?
3815            match operands {
3816                NumericBinaryOperands::Float(v1, v2) => Some(ExpressionTerm::FloatLiteral(v1 + v2)),
3817                NumericBinaryOperands::Double(v1, v2) => {
3818                    Some(ExpressionTerm::DoubleLiteral(v1 + v2))
3819                }
3820                NumericBinaryOperands::Integer(v1, v2) => {
3821                    v1.checked_add(v2).map(ExpressionTerm::IntegerLiteral)
3822                }
3823                NumericBinaryOperands::Decimal(v1, v2) => {
3824                    v1.checked_add(v2).map(ExpressionTerm::DecimalLiteral)
3825                }
3826                #[cfg(feature = "sep-0002")]
3827                _ => None,
3828            }
3829        } else {
3830            None
3831        };
3832    }
3833
3834    fn finish(&mut self) -> Option<ExpressionTerm> {
3835        self.sum.take()
3836    }
3837}
3838
3839#[derive(Default)]
3840struct AvgAccumulator {
3841    sum: SumAccumulator,
3842    count: i64,
3843}
3844
3845impl Accumulator for AvgAccumulator {
3846    fn add(&mut self, element: ExpressionTerm) {
3847        self.sum.add(element);
3848        self.count += 1;
3849    }
3850
3851    fn finish(&mut self) -> Option<ExpressionTerm> {
3852        let sum = self.sum.finish()?;
3853        if self.count == 0 {
3854            return Some(ExpressionTerm::IntegerLiteral(0.into()));
3855        }
3856        // TODO: duration?
3857        let count = Integer::from(self.count);
3858        match sum {
3859            ExpressionTerm::FloatLiteral(sum) => {
3860                Some(ExpressionTerm::FloatLiteral(sum / Float::from(count)))
3861            }
3862            ExpressionTerm::DoubleLiteral(sum) => {
3863                Some(ExpressionTerm::DoubleLiteral(sum / Double::from(count)))
3864            }
3865            ExpressionTerm::IntegerLiteral(sum) => Some(ExpressionTerm::DecimalLiteral(
3866                Decimal::from(sum).checked_div(count)?,
3867            )),
3868            ExpressionTerm::DecimalLiteral(sum) => {
3869                Some(ExpressionTerm::DecimalLiteral(sum.checked_div(count)?))
3870            }
3871            _ => None,
3872        }
3873    }
3874}
3875
3876#[derive(Default)]
3877#[allow(clippy::option_option)]
3878struct MinAccumulator {
3879    min: Option<Option<ExpressionTerm>>,
3880}
3881
3882impl Accumulator for MinAccumulator {
3883    fn add(&mut self, element: ExpressionTerm) {
3884        if let Some(min) = &self.min {
3885            if cmp_terms(Some(&element), min.as_ref()) == Ordering::Less {
3886                self.min = Some(Some(element));
3887            }
3888        } else {
3889            self.min = Some(Some(element))
3890        }
3891    }
3892
3893    fn finish(&mut self) -> Option<ExpressionTerm> {
3894        self.min.clone().and_then(|v| v)
3895    }
3896}
3897
3898#[derive(Default)]
3899#[allow(clippy::option_option)]
3900struct MaxAccumulator {
3901    max: Option<Option<ExpressionTerm>>,
3902}
3903
3904impl Accumulator for MaxAccumulator {
3905    fn add(&mut self, element: ExpressionTerm) {
3906        if let Some(max) = &self.max {
3907            if cmp_terms(Some(&element), max.as_ref()) == Ordering::Greater {
3908                self.max = Some(Some(element))
3909            }
3910        } else {
3911            self.max = Some(Some(element))
3912        }
3913    }
3914
3915    fn finish(&mut self) -> Option<ExpressionTerm> {
3916        self.max.clone().and_then(|v| v)
3917    }
3918}
3919
3920#[allow(clippy::option_option)]
3921struct GroupConcatAccumulator {
3922    concat: Option<String>,
3923    language: Option<Option<String>>,
3924    separator: Rc<str>,
3925}
3926
3927impl GroupConcatAccumulator {
3928    fn new(separator: Rc<str>) -> Self {
3929        Self {
3930            concat: Some(String::new()),
3931            language: None,
3932            separator,
3933        }
3934    }
3935}
3936
3937impl Accumulator for GroupConcatAccumulator {
3938    fn add(&mut self, element: ExpressionTerm) {
3939        let Some(concat) = self.concat.as_mut() else {
3940            return;
3941        };
3942        let Some((value, e_language)) = to_string_and_language(element) else {
3943            self.concat = None;
3944            return;
3945        };
3946        if let Some(lang) = &self.language {
3947            if *lang != e_language {
3948                self.language = Some(None)
3949            }
3950            concat.push_str(&self.separator);
3951        } else {
3952            self.language = Some(e_language)
3953        }
3954        concat.push_str(&value);
3955    }
3956
3957    fn finish(&mut self) -> Option<ExpressionTerm> {
3958        self.concat
3959            .take()
3960            .map(|result| build_plain_literal(result, self.language.take().flatten()))
3961    }
3962}
3963
3964fn encode_variable(variables: &mut Vec<Variable>, variable: &Variable) -> usize {
3965    if let Some(key) = slice_key(variables, variable) {
3966        key
3967    } else {
3968        variables.push(variable.clone());
3969        variables.len() - 1
3970    }
3971}
3972
3973fn bnode_key(blank_nodes: &mut Vec<BlankNode>, blank_node: &BlankNode) -> usize {
3974    if let Some(key) = slice_key(blank_nodes, blank_node) {
3975        key
3976    } else {
3977        blank_nodes.push(blank_node.clone());
3978        blank_nodes.len() - 1
3979    }
3980}
3981
3982fn slice_key<T: Eq>(slice: &[T], element: &T) -> Option<usize> {
3983    for (i, item) in slice.iter().enumerate() {
3984        if item == element {
3985            return Some(i);
3986        }
3987    }
3988    None
3989}
3990
3991/// Equality operator (=)
3992fn equals(a: &ExpressionTerm, b: &ExpressionTerm) -> Option<bool> {
3993    match a {
3994        ExpressionTerm::NamedNode(_)
3995        | ExpressionTerm::BlankNode(_)
3996        | ExpressionTerm::LangStringLiteral { .. } => Some(a == b),
3997        ExpressionTerm::StringLiteral(a) => match b {
3998            ExpressionTerm::StringLiteral(b) => Some(a == b),
3999            ExpressionTerm::OtherTypedLiteral { .. } => None,
4000            _ => Some(false),
4001        },
4002        ExpressionTerm::OtherTypedLiteral { .. } => match b {
4003            ExpressionTerm::OtherTypedLiteral { .. } if a == b => Some(true),
4004            ExpressionTerm::NamedNode(_)
4005            | ExpressionTerm::BlankNode(_)
4006            | ExpressionTerm::LangStringLiteral { .. } => Some(false),
4007            #[cfg(feature = "rdf-star")]
4008            ExpressionTerm::Triple(_) => Some(false),
4009            _ => None,
4010        },
4011        ExpressionTerm::BooleanLiteral(a) => match b {
4012            ExpressionTerm::BooleanLiteral(b) => Some(a == b),
4013            ExpressionTerm::OtherTypedLiteral { .. } => None,
4014            _ => Some(false),
4015        },
4016        ExpressionTerm::FloatLiteral(a) => match b {
4017            ExpressionTerm::FloatLiteral(b) => Some(a == b),
4018            ExpressionTerm::DoubleLiteral(b) => Some(Double::from(*a) == *b),
4019            ExpressionTerm::IntegerLiteral(b) => Some(*a == (*b).into()),
4020            ExpressionTerm::DecimalLiteral(b) => Some(*a == (*b).into()),
4021            ExpressionTerm::OtherTypedLiteral { .. } => None,
4022            _ => Some(false),
4023        },
4024        ExpressionTerm::DoubleLiteral(a) => match b {
4025            ExpressionTerm::FloatLiteral(b) => Some(*a == (*b).into()),
4026            ExpressionTerm::DoubleLiteral(b) => Some(a == b),
4027            ExpressionTerm::IntegerLiteral(b) => Some(*a == (*b).into()),
4028            ExpressionTerm::DecimalLiteral(b) => Some(*a == (*b).into()),
4029            ExpressionTerm::OtherTypedLiteral { .. } => None,
4030            _ => Some(false),
4031        },
4032        ExpressionTerm::IntegerLiteral(a) => match b {
4033            ExpressionTerm::FloatLiteral(b) => Some(Float::from(*a) == *b),
4034            ExpressionTerm::DoubleLiteral(b) => Some(Double::from(*a) == *b),
4035            ExpressionTerm::IntegerLiteral(b) => Some(a == b),
4036            ExpressionTerm::DecimalLiteral(b) => Some(Decimal::from(*a) == *b),
4037            ExpressionTerm::OtherTypedLiteral { .. } => None,
4038            _ => Some(false),
4039        },
4040        ExpressionTerm::DecimalLiteral(a) => match b {
4041            ExpressionTerm::FloatLiteral(b) => Some(Float::from(*a) == *b),
4042            ExpressionTerm::DoubleLiteral(b) => Some(Double::from(*a) == *b),
4043            ExpressionTerm::IntegerLiteral(b) => Some(*a == (*b).into()),
4044            ExpressionTerm::DecimalLiteral(b) => Some(a == b),
4045            ExpressionTerm::OtherTypedLiteral { .. } => None,
4046            _ => Some(false),
4047        },
4048        ExpressionTerm::DateTimeLiteral(a) => match b {
4049            ExpressionTerm::DateTimeLiteral(b) => Some(a == b),
4050            ExpressionTerm::OtherTypedLiteral { .. } => None,
4051            _ => Some(false),
4052        },
4053        #[cfg(feature = "sep-0002")]
4054        ExpressionTerm::TimeLiteral(a) => match b {
4055            ExpressionTerm::TimeLiteral(b) => Some(a == b),
4056            ExpressionTerm::OtherTypedLiteral { .. } => None,
4057            _ => Some(false),
4058        },
4059        #[cfg(feature = "sep-0002")]
4060        ExpressionTerm::DateLiteral(a) => match b {
4061            ExpressionTerm::DateLiteral(b) => Some(a == b),
4062            ExpressionTerm::OtherTypedLiteral { .. } => None,
4063            _ => Some(false),
4064        },
4065        #[cfg(feature = "calendar-ext")]
4066        ExpressionTerm::GYearMonthLiteral(a) => match b {
4067            ExpressionTerm::GYearMonthLiteral(b) => Some(a == b),
4068            ExpressionTerm::OtherTypedLiteral { .. } => None,
4069            _ => Some(false),
4070        },
4071        #[cfg(feature = "calendar-ext")]
4072        ExpressionTerm::GYearLiteral(a) => match b {
4073            ExpressionTerm::GYearLiteral(b) => Some(a == b),
4074            ExpressionTerm::OtherTypedLiteral { .. } => None,
4075            _ => Some(false),
4076        },
4077        #[cfg(feature = "calendar-ext")]
4078        ExpressionTerm::GMonthDayLiteral(a) => match b {
4079            ExpressionTerm::GMonthDayLiteral(b) => Some(a == b),
4080            ExpressionTerm::OtherTypedLiteral { .. } => None,
4081            _ => Some(false),
4082        },
4083        #[cfg(feature = "calendar-ext")]
4084        ExpressionTerm::GDayLiteral(a) => match b {
4085            ExpressionTerm::GDayLiteral(b) => Some(a == b),
4086            ExpressionTerm::OtherTypedLiteral { .. } => None,
4087            _ => Some(false),
4088        },
4089        #[cfg(feature = "calendar-ext")]
4090        ExpressionTerm::GMonthLiteral(a) => match b {
4091            ExpressionTerm::GMonthLiteral(b) => Some(a == b),
4092            ExpressionTerm::OtherTypedLiteral { .. } => None,
4093            _ => Some(false),
4094        },
4095        #[cfg(feature = "sep-0002")]
4096        ExpressionTerm::DurationLiteral(a) => match b {
4097            ExpressionTerm::DurationLiteral(b) => Some(a == b),
4098            ExpressionTerm::YearMonthDurationLiteral(b) => Some(a == b),
4099            ExpressionTerm::DayTimeDurationLiteral(b) => Some(a == b),
4100            ExpressionTerm::OtherTypedLiteral { .. } => None,
4101            _ => Some(false),
4102        },
4103        #[cfg(feature = "sep-0002")]
4104        ExpressionTerm::YearMonthDurationLiteral(a) => match b {
4105            ExpressionTerm::DurationLiteral(b) => Some(a == b),
4106            ExpressionTerm::YearMonthDurationLiteral(b) => Some(a == b),
4107            ExpressionTerm::DayTimeDurationLiteral(b) => Some(a == b),
4108            ExpressionTerm::OtherTypedLiteral { .. } => None,
4109            _ => Some(false),
4110        },
4111        #[cfg(feature = "sep-0002")]
4112        ExpressionTerm::DayTimeDurationLiteral(a) => match b {
4113            ExpressionTerm::DurationLiteral(b) => Some(a == b),
4114            ExpressionTerm::YearMonthDurationLiteral(b) => Some(a == b),
4115            ExpressionTerm::DayTimeDurationLiteral(b) => Some(a == b),
4116            ExpressionTerm::OtherTypedLiteral { .. } => None,
4117            _ => Some(false),
4118        },
4119        #[cfg(feature = "rdf-star")]
4120        ExpressionTerm::Triple(a) => {
4121            if let ExpressionTerm::Triple(b) = b {
4122                triple_equals(a, b)
4123            } else {
4124                Some(false)
4125            }
4126        }
4127    }
4128}
4129
4130#[cfg(feature = "rdf-star")]
4131fn triple_equals(a: &ExpressionTriple, b: &ExpressionTriple) -> Option<bool> {
4132    Some(
4133        match &a.subject {
4134            ExpressionSubject::NamedNode(_) | ExpressionSubject::BlankNode(_) => {
4135                a.subject == b.subject
4136            }
4137            ExpressionSubject::Triple(a) => {
4138                if let ExpressionSubject::Triple(b) = &b.subject {
4139                    triple_equals(a, b)?
4140                } else {
4141                    false
4142                }
4143            }
4144        } && a.predicate == b.predicate
4145            && equals(&a.object, &b.object)?,
4146    )
4147}
4148
4149/// Comparison for ordering
4150fn cmp_terms(a: Option<&ExpressionTerm>, b: Option<&ExpressionTerm>) -> Ordering {
4151    match (a, b) {
4152        (Some(a), Some(b)) => {
4153            match a {
4154                ExpressionTerm::BlankNode(a) => match b {
4155                    ExpressionTerm::BlankNode(b) => a.as_str().cmp(b.as_str()),
4156                    _ => Ordering::Less,
4157                },
4158                ExpressionTerm::NamedNode(a) => match b {
4159                    ExpressionTerm::BlankNode(_) => Ordering::Greater,
4160                    ExpressionTerm::NamedNode(b) => a.as_str().cmp(b.as_str()),
4161                    _ => Ordering::Less,
4162                },
4163                #[cfg(feature = "rdf-star")]
4164                ExpressionTerm::Triple(a) => match b {
4165                    ExpressionTerm::Triple(b) => cmp_triples(a, b),
4166                    _ => Ordering::Greater,
4167                },
4168                _ => match b {
4169                    ExpressionTerm::NamedNode(_) | ExpressionTerm::BlankNode(_) => {
4170                        Ordering::Greater
4171                    }
4172                    #[cfg(feature = "rdf-star")]
4173                    ExpressionTerm::Triple(_) => Ordering::Less,
4174                    _ => {
4175                        if let Some(ord) = partial_cmp_literals(a, b) {
4176                            ord
4177                        } else if let (Term::Literal(a), Term::Literal(b)) =
4178                            (a.clone().into(), b.clone().into())
4179                        {
4180                            (a.value(), a.datatype(), a.language()).cmp(&(
4181                                b.value(),
4182                                b.datatype(),
4183                                b.language(),
4184                            ))
4185                        } else {
4186                            Ordering::Equal // Should never happen
4187                        }
4188                    }
4189                },
4190            }
4191        }
4192        (Some(_), None) => Ordering::Greater,
4193        (None, Some(_)) => Ordering::Less,
4194        (None, None) => Ordering::Equal,
4195    }
4196}
4197
4198#[cfg(feature = "rdf-star")]
4199fn cmp_triples(a: &ExpressionTriple, b: &ExpressionTriple) -> Ordering {
4200    match match &a.subject {
4201        ExpressionSubject::BlankNode(a) => match &b.subject {
4202            ExpressionSubject::BlankNode(b) => a.as_str().cmp(b.as_str()),
4203            ExpressionSubject::NamedNode(_) => Ordering::Less,
4204            #[cfg(feature = "rdf-star")]
4205            ExpressionSubject::Triple(_) => Ordering::Less,
4206        },
4207        ExpressionSubject::NamedNode(a) => match &b.subject {
4208            ExpressionSubject::BlankNode(_) => Ordering::Greater,
4209            ExpressionSubject::NamedNode(b) => a.as_str().cmp(b.as_str()),
4210            #[cfg(feature = "rdf-star")]
4211            ExpressionSubject::Triple(_) => Ordering::Less,
4212        },
4213        ExpressionSubject::Triple(a) => match &b.subject {
4214            ExpressionSubject::Triple(b) => cmp_triples(a, b),
4215            _ => Ordering::Greater,
4216        },
4217    } {
4218        Ordering::Equal => match a.predicate.as_str().cmp(b.predicate.as_str()) {
4219            Ordering::Equal => cmp_terms(Some(&a.object), Some(&b.object)),
4220            o => o,
4221        },
4222        o => o,
4223    }
4224}
4225
4226/// Comparison for <, >, <= and >= operators
4227fn partial_cmp(a: &ExpressionTerm, b: &ExpressionTerm) -> Option<Ordering> {
4228    if a == b {
4229        return Some(Ordering::Equal);
4230    }
4231    #[cfg(feature = "rdf-star")]
4232    if let ExpressionTerm::Triple(a) = a {
4233        return if let ExpressionTerm::Triple(b) = b {
4234            partial_cmp_triples(a, b)
4235        } else {
4236            None
4237        };
4238    }
4239    partial_cmp_literals(a, b)
4240}
4241
4242fn partial_cmp_literals(a: &ExpressionTerm, b: &ExpressionTerm) -> Option<Ordering> {
4243    match a {
4244        ExpressionTerm::StringLiteral(a) => {
4245            if let ExpressionTerm::StringLiteral(b) = b {
4246                a.partial_cmp(b)
4247            } else {
4248                None
4249            }
4250        }
4251        ExpressionTerm::LangStringLiteral {
4252            value: va,
4253            language: la,
4254        } => {
4255            if let ExpressionTerm::LangStringLiteral {
4256                value: vb,
4257                language: lb,
4258            } = b
4259            {
4260                if la == lb {
4261                    va.partial_cmp(vb)
4262                } else {
4263                    None
4264                }
4265            } else {
4266                None
4267            }
4268        }
4269        ExpressionTerm::FloatLiteral(a) => match b {
4270            ExpressionTerm::FloatLiteral(b) => a.partial_cmp(b),
4271            ExpressionTerm::DoubleLiteral(b) => Double::from(*a).partial_cmp(b),
4272            ExpressionTerm::IntegerLiteral(b) => a.partial_cmp(&Float::from(*b)),
4273            ExpressionTerm::DecimalLiteral(b) => a.partial_cmp(&(*b).into()),
4274            _ => None,
4275        },
4276        ExpressionTerm::DoubleLiteral(a) => match b {
4277            ExpressionTerm::FloatLiteral(b) => a.partial_cmp(&(*b).into()),
4278            ExpressionTerm::DoubleLiteral(b) => a.partial_cmp(b),
4279            ExpressionTerm::IntegerLiteral(b) => a.partial_cmp(&Double::from(*b)),
4280            ExpressionTerm::DecimalLiteral(b) => a.partial_cmp(&(*b).into()),
4281            _ => None,
4282        },
4283        ExpressionTerm::IntegerLiteral(a) => match b {
4284            ExpressionTerm::FloatLiteral(b) => Float::from(*a).partial_cmp(b),
4285            ExpressionTerm::DoubleLiteral(b) => Double::from(*a).partial_cmp(b),
4286            ExpressionTerm::IntegerLiteral(b) => a.partial_cmp(b),
4287            ExpressionTerm::DecimalLiteral(b) => Decimal::from(*a).partial_cmp(b),
4288            _ => None,
4289        },
4290        ExpressionTerm::DecimalLiteral(a) => match b {
4291            ExpressionTerm::FloatLiteral(b) => Float::from(*a).partial_cmp(b),
4292            ExpressionTerm::DoubleLiteral(b) => Double::from(*a).partial_cmp(b),
4293            ExpressionTerm::IntegerLiteral(b) => a.partial_cmp(&Decimal::from(*b)),
4294            ExpressionTerm::DecimalLiteral(b) => a.partial_cmp(b),
4295            _ => None,
4296        },
4297        ExpressionTerm::DateTimeLiteral(a) => {
4298            if let ExpressionTerm::DateTimeLiteral(b) = b {
4299                a.partial_cmp(b)
4300            } else {
4301                None
4302            }
4303        }
4304        #[cfg(feature = "sep-0002")]
4305        ExpressionTerm::TimeLiteral(a) => {
4306            if let ExpressionTerm::TimeLiteral(b) = b {
4307                a.partial_cmp(b)
4308            } else {
4309                None
4310            }
4311        }
4312        #[cfg(feature = "sep-0002")]
4313        ExpressionTerm::DateLiteral(a) => {
4314            if let ExpressionTerm::DateLiteral(b) = b {
4315                a.partial_cmp(b)
4316            } else {
4317                None
4318            }
4319        }
4320        #[cfg(feature = "calendar-ext")]
4321        ExpressionTerm::GYearMonthLiteral(a) => {
4322            if let ExpressionTerm::GYearMonthLiteral(b) = b {
4323                a.partial_cmp(b)
4324            } else {
4325                None
4326            }
4327        }
4328        #[cfg(feature = "calendar-ext")]
4329        ExpressionTerm::GYearLiteral(a) => {
4330            if let ExpressionTerm::GYearLiteral(b) = b {
4331                a.partial_cmp(b)
4332            } else {
4333                None
4334            }
4335        }
4336        #[cfg(feature = "calendar-ext")]
4337        ExpressionTerm::GMonthDayLiteral(a) => {
4338            if let ExpressionTerm::GMonthDayLiteral(b) = b {
4339                a.partial_cmp(b)
4340            } else {
4341                None
4342            }
4343        }
4344        #[cfg(feature = "calendar-ext")]
4345        ExpressionTerm::GDayLiteral(a) => {
4346            if let ExpressionTerm::GDayLiteral(b) = b {
4347                a.partial_cmp(b)
4348            } else {
4349                None
4350            }
4351        }
4352        #[cfg(feature = "calendar-ext")]
4353        ExpressionTerm::GMonthLiteral(a) => {
4354            if let ExpressionTerm::GMonthLiteral(b) = b {
4355                a.partial_cmp(b)
4356            } else {
4357                None
4358            }
4359        }
4360        #[cfg(feature = "sep-0002")]
4361        ExpressionTerm::DurationLiteral(a) => match b {
4362            ExpressionTerm::DurationLiteral(b) => a.partial_cmp(b),
4363            ExpressionTerm::YearMonthDurationLiteral(b) => a.partial_cmp(b),
4364            ExpressionTerm::DayTimeDurationLiteral(b) => a.partial_cmp(b),
4365            _ => None,
4366        },
4367        #[cfg(feature = "sep-0002")]
4368        ExpressionTerm::YearMonthDurationLiteral(a) => match b {
4369            ExpressionTerm::DurationLiteral(b) => a.partial_cmp(b),
4370            ExpressionTerm::YearMonthDurationLiteral(b) => a.partial_cmp(b),
4371            ExpressionTerm::DayTimeDurationLiteral(b) => a.partial_cmp(b),
4372            _ => None,
4373        },
4374        #[cfg(feature = "sep-0002")]
4375        ExpressionTerm::DayTimeDurationLiteral(a) => match b {
4376            ExpressionTerm::DurationLiteral(b) => a.partial_cmp(b),
4377            ExpressionTerm::YearMonthDurationLiteral(b) => a.partial_cmp(b),
4378            ExpressionTerm::DayTimeDurationLiteral(b) => a.partial_cmp(b),
4379            _ => None,
4380        },
4381        _ => None,
4382    }
4383}
4384
4385#[cfg(feature = "rdf-star")]
4386fn partial_cmp_triples(a: &ExpressionTriple, b: &ExpressionTriple) -> Option<Ordering> {
4387    // We compare subjects
4388    match (&a.subject, &b.subject) {
4389        (ExpressionSubject::NamedNode(a), ExpressionSubject::NamedNode(b)) => {
4390            if a != b {
4391                return None;
4392            }
4393        }
4394        (ExpressionSubject::BlankNode(a), ExpressionSubject::BlankNode(b)) => {
4395            if a != b {
4396                return None;
4397            }
4398        }
4399        (ExpressionSubject::Triple(a), ExpressionSubject::Triple(b)) => {
4400            match partial_cmp_triples(a, b)? {
4401                Ordering::Equal => (),
4402                o => return Some(o),
4403            }
4404        }
4405        _ => return None,
4406    }
4407    if a.predicate != b.predicate {
4408        return None;
4409    }
4410    partial_cmp(&a.object, &b.object)
4411}
4412
4413enum NumericBinaryOperands {
4414    Float(Float, Float),
4415    Double(Double, Double),
4416    Integer(Integer, Integer),
4417    Decimal(Decimal, Decimal),
4418    #[cfg(feature = "sep-0002")]
4419    Duration(Duration, Duration),
4420    #[cfg(feature = "sep-0002")]
4421    YearMonthDuration(YearMonthDuration, YearMonthDuration),
4422    #[cfg(feature = "sep-0002")]
4423    DayTimeDuration(DayTimeDuration, DayTimeDuration),
4424    #[cfg(feature = "sep-0002")]
4425    DateTime(DateTime, DateTime),
4426    #[cfg(feature = "sep-0002")]
4427    Time(Time, Time),
4428    #[cfg(feature = "sep-0002")]
4429    Date(Date, Date),
4430    #[cfg(feature = "sep-0002")]
4431    DateTimeDuration(DateTime, Duration),
4432    #[cfg(feature = "sep-0002")]
4433    DateTimeYearMonthDuration(DateTime, YearMonthDuration),
4434    #[cfg(feature = "sep-0002")]
4435    DateTimeDayTimeDuration(DateTime, DayTimeDuration),
4436    #[cfg(feature = "sep-0002")]
4437    DateDuration(Date, Duration),
4438    #[cfg(feature = "sep-0002")]
4439    DateYearMonthDuration(Date, YearMonthDuration),
4440    #[cfg(feature = "sep-0002")]
4441    DateDayTimeDuration(Date, DayTimeDuration),
4442    #[cfg(feature = "sep-0002")]
4443    TimeDuration(Time, Duration),
4444    #[cfg(feature = "sep-0002")]
4445    TimeDayTimeDuration(Time, DayTimeDuration),
4446}
4447
4448impl NumericBinaryOperands {
4449    fn new(a: ExpressionTerm, b: ExpressionTerm) -> Option<Self> {
4450        match (a, b) {
4451            (ExpressionTerm::FloatLiteral(v1), ExpressionTerm::FloatLiteral(v2)) => {
4452                Some(Self::Float(v1, v2))
4453            }
4454            (ExpressionTerm::FloatLiteral(v1), ExpressionTerm::DoubleLiteral(v2)) => {
4455                Some(Self::Double(v1.into(), v2))
4456            }
4457            (ExpressionTerm::FloatLiteral(v1), ExpressionTerm::IntegerLiteral(v2)) => {
4458                Some(Self::Float(v1, v2.into()))
4459            }
4460            (ExpressionTerm::FloatLiteral(v1), ExpressionTerm::DecimalLiteral(v2)) => {
4461                Some(Self::Float(v1, v2.into()))
4462            }
4463            (ExpressionTerm::DoubleLiteral(v1), ExpressionTerm::FloatLiteral(v2)) => {
4464                Some(Self::Double(v1, v2.into()))
4465            }
4466            (ExpressionTerm::DoubleLiteral(v1), ExpressionTerm::DoubleLiteral(v2)) => {
4467                Some(Self::Double(v1, v2))
4468            }
4469            (ExpressionTerm::DoubleLiteral(v1), ExpressionTerm::IntegerLiteral(v2)) => {
4470                Some(Self::Double(v1, v2.into()))
4471            }
4472            (ExpressionTerm::DoubleLiteral(v1), ExpressionTerm::DecimalLiteral(v2)) => {
4473                Some(Self::Double(v1, v2.into()))
4474            }
4475            (ExpressionTerm::IntegerLiteral(v1), ExpressionTerm::FloatLiteral(v2)) => {
4476                Some(Self::Float(v1.into(), v2))
4477            }
4478            (ExpressionTerm::IntegerLiteral(v1), ExpressionTerm::DoubleLiteral(v2)) => {
4479                Some(Self::Double(v1.into(), v2))
4480            }
4481            (ExpressionTerm::IntegerLiteral(v1), ExpressionTerm::IntegerLiteral(v2)) => {
4482                Some(Self::Integer(v1, v2))
4483            }
4484            (ExpressionTerm::IntegerLiteral(v1), ExpressionTerm::DecimalLiteral(v2)) => {
4485                Some(Self::Decimal(v1.into(), v2))
4486            }
4487            (ExpressionTerm::DecimalLiteral(v1), ExpressionTerm::FloatLiteral(v2)) => {
4488                Some(Self::Float(v1.into(), v2))
4489            }
4490            (ExpressionTerm::DecimalLiteral(v1), ExpressionTerm::DoubleLiteral(v2)) => {
4491                Some(Self::Double(v1.into(), v2))
4492            }
4493            (ExpressionTerm::DecimalLiteral(v1), ExpressionTerm::IntegerLiteral(v2)) => {
4494                Some(Self::Decimal(v1, v2.into()))
4495            }
4496            (ExpressionTerm::DecimalLiteral(v1), ExpressionTerm::DecimalLiteral(v2)) => {
4497                Some(Self::Decimal(v1, v2))
4498            }
4499            #[cfg(feature = "sep-0002")]
4500            (ExpressionTerm::DurationLiteral(v1), ExpressionTerm::DurationLiteral(v2)) => {
4501                Some(Self::Duration(v1, v2))
4502            }
4503            #[cfg(feature = "sep-0002")]
4504            (ExpressionTerm::DurationLiteral(v1), ExpressionTerm::YearMonthDurationLiteral(v2)) => {
4505                Some(Self::Duration(v1, v2.into()))
4506            }
4507            #[cfg(feature = "sep-0002")]
4508            (ExpressionTerm::DurationLiteral(v1), ExpressionTerm::DayTimeDurationLiteral(v2)) => {
4509                Some(Self::Duration(v1, v2.into()))
4510            }
4511            #[cfg(feature = "sep-0002")]
4512            (ExpressionTerm::YearMonthDurationLiteral(v1), ExpressionTerm::DurationLiteral(v2)) => {
4513                Some(Self::Duration(v1.into(), v2))
4514            }
4515            #[cfg(feature = "sep-0002")]
4516            (
4517                ExpressionTerm::YearMonthDurationLiteral(v1),
4518                ExpressionTerm::YearMonthDurationLiteral(v2),
4519            ) => Some(Self::YearMonthDuration(v1, v2)),
4520            #[cfg(feature = "sep-0002")]
4521            (
4522                ExpressionTerm::YearMonthDurationLiteral(v1),
4523                ExpressionTerm::DayTimeDurationLiteral(v2),
4524            ) => Some(Self::Duration(v1.into(), v2.into())),
4525            #[cfg(feature = "sep-0002")]
4526            (ExpressionTerm::DayTimeDurationLiteral(v1), ExpressionTerm::DurationLiteral(v2)) => {
4527                Some(Self::Duration(v1.into(), v2))
4528            }
4529            #[cfg(feature = "sep-0002")]
4530            (
4531                ExpressionTerm::DayTimeDurationLiteral(v1),
4532                ExpressionTerm::YearMonthDurationLiteral(v2),
4533            ) => Some(Self::Duration(v1.into(), v2.into())),
4534            #[cfg(feature = "sep-0002")]
4535            (
4536                ExpressionTerm::DayTimeDurationLiteral(v1),
4537                ExpressionTerm::DayTimeDurationLiteral(v2),
4538            ) => Some(Self::DayTimeDuration(v1, v2)),
4539            #[cfg(feature = "sep-0002")]
4540            (ExpressionTerm::DateTimeLiteral(v1), ExpressionTerm::DateTimeLiteral(v2)) => {
4541                Some(Self::DateTime(v1, v2))
4542            }
4543            #[cfg(feature = "sep-0002")]
4544            (ExpressionTerm::DateLiteral(v1), ExpressionTerm::DateLiteral(v2)) => {
4545                Some(Self::Date(v1, v2))
4546            }
4547            #[cfg(feature = "sep-0002")]
4548            (ExpressionTerm::TimeLiteral(v1), ExpressionTerm::TimeLiteral(v2)) => {
4549                Some(Self::Time(v1, v2))
4550            }
4551            #[cfg(feature = "sep-0002")]
4552            (ExpressionTerm::DateTimeLiteral(v1), ExpressionTerm::DurationLiteral(v2)) => {
4553                Some(Self::DateTimeDuration(v1, v2))
4554            }
4555            #[cfg(feature = "sep-0002")]
4556            (ExpressionTerm::DateTimeLiteral(v1), ExpressionTerm::YearMonthDurationLiteral(v2)) => {
4557                Some(Self::DateTimeYearMonthDuration(v1, v2))
4558            }
4559            #[cfg(feature = "sep-0002")]
4560            (ExpressionTerm::DateTimeLiteral(v1), ExpressionTerm::DayTimeDurationLiteral(v2)) => {
4561                Some(Self::DateTimeDayTimeDuration(v1, v2))
4562            }
4563            #[cfg(feature = "sep-0002")]
4564            (ExpressionTerm::DateLiteral(v1), ExpressionTerm::DurationLiteral(v2)) => {
4565                Some(Self::DateDuration(v1, v2))
4566            }
4567            #[cfg(feature = "sep-0002")]
4568            (ExpressionTerm::DateLiteral(v1), ExpressionTerm::YearMonthDurationLiteral(v2)) => {
4569                Some(Self::DateYearMonthDuration(v1, v2))
4570            }
4571            #[cfg(feature = "sep-0002")]
4572            (ExpressionTerm::DateLiteral(v1), ExpressionTerm::DayTimeDurationLiteral(v2)) => {
4573                Some(Self::DateDayTimeDuration(v1, v2))
4574            }
4575            #[cfg(feature = "sep-0002")]
4576            (ExpressionTerm::TimeLiteral(v1), ExpressionTerm::DurationLiteral(v2)) => {
4577                Some(Self::TimeDuration(v1, v2))
4578            }
4579            #[cfg(feature = "sep-0002")]
4580            (ExpressionTerm::TimeLiteral(v1), ExpressionTerm::DayTimeDurationLiteral(v2)) => {
4581                Some(Self::TimeDayTimeDuration(v1, v2))
4582            }
4583            _ => None,
4584        }
4585    }
4586}
4587
4588enum TupleSelector<D: QueryableDataset> {
4589    Constant(D::InternalTerm),
4590    Variable(usize),
4591    #[cfg(feature = "rdf-star")]
4592    TriplePattern(Rc<TripleTupleSelector<D>>),
4593}
4594
4595impl<D: QueryableDataset> TupleSelector<D> {
4596    fn from_ground_term_pattern(
4597        term_pattern: &GroundTermPattern,
4598        variables: &mut Vec<Variable>,
4599        dataset: &EvalDataset<D>,
4600    ) -> Result<Self, QueryEvaluationError> {
4601        Ok(match term_pattern {
4602            GroundTermPattern::Variable(variable) => {
4603                Self::Variable(encode_variable(variables, variable))
4604            }
4605            GroundTermPattern::NamedNode(term) => {
4606                Self::Constant(dataset.internalize_term(term.as_ref().into())?)
4607            }
4608            GroundTermPattern::Literal(term) => {
4609                Self::Constant(dataset.internalize_term(term.as_ref().into())?)
4610            }
4611            #[cfg(feature = "rdf-star")]
4612            GroundTermPattern::Triple(triple) => {
4613                match (
4614                    Self::from_ground_term_pattern(&triple.subject, variables, dataset)?,
4615                    Self::from_named_node_pattern(&triple.predicate, variables, dataset)?,
4616                    Self::from_ground_term_pattern(&triple.object, variables, dataset)?,
4617                ) {
4618                    (
4619                        Self::Constant(subject),
4620                        Self::Constant(predicate),
4621                        Self::Constant(object),
4622                    ) => Self::Constant(
4623                        dataset.internalize_expression_term(
4624                            ExpressionTriple::new(
4625                                dataset.externalize_expression_term(subject)?,
4626                                dataset.externalize_expression_term(predicate)?,
4627                                dataset.externalize_expression_term(object)?,
4628                            )
4629                            .ok_or_else(|| QueryEvaluationError::InvalidStorageTripleTerm)?
4630                            .into(),
4631                        )?,
4632                    ),
4633                    (subject, predicate, object) => {
4634                        Self::TriplePattern(Rc::new(TripleTupleSelector {
4635                            subject,
4636                            predicate,
4637                            object,
4638                        }))
4639                    }
4640                }
4641            }
4642        })
4643    }
4644
4645    fn from_named_node_pattern(
4646        named_node_pattern: &NamedNodePattern,
4647        variables: &mut Vec<Variable>,
4648        dataset: &EvalDataset<D>,
4649    ) -> Result<Self, QueryEvaluationError> {
4650        Ok(match named_node_pattern {
4651            NamedNodePattern::Variable(variable) => {
4652                Self::Variable(encode_variable(variables, variable))
4653            }
4654            NamedNodePattern::NamedNode(term) => {
4655                Self::Constant(dataset.internalize_term(term.as_ref().into())?)
4656            }
4657        })
4658    }
4659
4660    #[cfg_attr(not(feature = "rdf-star"), allow(clippy::unnecessary_wraps))]
4661    fn get_pattern_value(
4662        &self,
4663        tuple: &InternalTuple<D>,
4664        #[cfg(feature = "rdf-star")] dataset: &EvalDataset<D>,
4665    ) -> Result<Option<D::InternalTerm>, QueryEvaluationError> {
4666        Ok(match self {
4667            Self::Constant(c) => Some(c.clone()),
4668            Self::Variable(v) => tuple.get(*v).cloned(),
4669            #[cfg(feature = "rdf-star")]
4670            Self::TriplePattern(triple) => {
4671                let Some(subject) = triple.subject.get_pattern_value(tuple, dataset)? else {
4672                    return Ok(None);
4673                };
4674                let Some(predicate) = triple.predicate.get_pattern_value(tuple, dataset)? else {
4675                    return Ok(None);
4676                };
4677                let Some(object) = triple.object.get_pattern_value(tuple, dataset)? else {
4678                    return Ok(None);
4679                };
4680                Some(
4681                    dataset.internalize_expression_term(
4682                        ExpressionTriple::new(
4683                            dataset.externalize_expression_term(subject)?,
4684                            dataset.externalize_expression_term(predicate)?,
4685                            dataset.externalize_expression_term(object)?,
4686                        )
4687                        .ok_or(QueryEvaluationError::InvalidStorageTripleTerm)?
4688                        .into(),
4689                    )?,
4690                )
4691            }
4692        })
4693    }
4694}
4695
4696impl<D: QueryableDataset> Clone for TupleSelector<D> {
4697    fn clone(&self) -> Self {
4698        match self {
4699            Self::Constant(c) => Self::Constant(c.clone()),
4700            Self::Variable(v) => Self::Variable(*v),
4701            #[cfg(feature = "rdf-star")]
4702            Self::TriplePattern(t) => Self::TriplePattern(Rc::clone(t)),
4703        }
4704    }
4705}
4706
4707#[cfg(feature = "rdf-star")]
4708struct TripleTupleSelector<D: QueryableDataset> {
4709    subject: TupleSelector<D>,
4710    predicate: TupleSelector<D>,
4711    object: TupleSelector<D>,
4712}
4713
4714#[cfg_attr(not(feature = "rdf-star"), allow(clippy::unnecessary_wraps))]
4715fn put_pattern_value<D: QueryableDataset>(
4716    selector: &TupleSelector<D>,
4717    value: D::InternalTerm,
4718    tuple: &mut InternalTuple<D>,
4719    #[cfg(feature = "rdf-star")] dataset: &EvalDataset<D>,
4720) -> Result<bool, QueryEvaluationError> {
4721    Ok(match selector {
4722        TupleSelector::Constant(c) => *c == value,
4723        TupleSelector::Variable(v) => {
4724            if let Some(old) = tuple.get(*v) {
4725                value == *old
4726            } else {
4727                tuple.set(*v, value);
4728                true
4729            }
4730        }
4731        #[cfg(feature = "rdf-star")]
4732        TupleSelector::TriplePattern(triple) => {
4733            let ExpressionTerm::Triple(value) = dataset.externalize_expression_term(value)? else {
4734                return Ok(false);
4735            };
4736            put_pattern_value(
4737                &triple.subject,
4738                dataset.internalize_expression_term(value.subject.into())?,
4739                tuple,
4740                dataset,
4741            )? && put_pattern_value(
4742                &triple.predicate,
4743                dataset.internalize_expression_term(value.predicate.into())?,
4744                tuple,
4745                dataset,
4746            )? && put_pattern_value(
4747                &triple.object,
4748                dataset.internalize_expression_term(value.object)?,
4749                tuple,
4750                dataset,
4751            )?
4752        }
4753    })
4754}
4755
4756pub fn are_compatible_and_not_disjointed<D: QueryableDataset>(
4757    a: &InternalTuple<D>,
4758    b: &InternalTuple<D>,
4759) -> bool {
4760    let mut found_intersection = false;
4761    for (a_value, b_value) in a.iter().zip(b.iter()) {
4762        if let (Some(a_value), Some(b_value)) = (a_value, b_value) {
4763            if a_value != b_value {
4764                return false;
4765            }
4766            found_intersection = true;
4767        }
4768    }
4769    found_intersection
4770}
4771
4772pub enum PropertyPath<D: QueryableDataset> {
4773    Path(D::InternalTerm),
4774    Reverse(Rc<Self>),
4775    Sequence(Rc<Self>, Rc<Self>),
4776    Alternative(Rc<Self>, Rc<Self>),
4777    ZeroOrMore(Rc<Self>),
4778    OneOrMore(Rc<Self>),
4779    ZeroOrOne(Rc<Self>),
4780    NegatedPropertySet(Rc<[D::InternalTerm]>),
4781}
4782
4783struct PathEvaluator<D: QueryableDataset> {
4784    dataset: EvalDataset<D>,
4785}
4786
4787impl<D: QueryableDataset> PathEvaluator<D> {
4788    fn eval_closed_in_graph(
4789        &self,
4790        path: &PropertyPath<D>,
4791        start: &D::InternalTerm,
4792        end: &D::InternalTerm,
4793        graph_name: Option<&D::InternalTerm>,
4794    ) -> Result<bool, QueryEvaluationError> {
4795        Ok(match path {
4796            PropertyPath::Path(p) => self
4797                .dataset
4798                .internal_quads_for_pattern(Some(start), Some(p), Some(end), Some(graph_name))
4799                .next()
4800                .transpose()?
4801                .is_some(),
4802            PropertyPath::Reverse(p) => self.eval_closed_in_graph(p, end, start, graph_name)?,
4803            PropertyPath::Sequence(a, b) => self
4804                .eval_from_in_graph(a, start, graph_name)
4805                .find_map(|middle| {
4806                    middle
4807                        .and_then(|middle| {
4808                            Ok(self
4809                                .eval_closed_in_graph(b, &middle, end, graph_name)?
4810                                .then_some(()))
4811                        })
4812                        .transpose()
4813                })
4814                .transpose()?
4815                .is_some(),
4816            PropertyPath::Alternative(a, b) => {
4817                self.eval_closed_in_graph(a, start, end, graph_name)?
4818                    || self.eval_closed_in_graph(b, start, end, graph_name)?
4819            }
4820            PropertyPath::ZeroOrMore(p) => {
4821                if start == end {
4822                    self.is_subject_or_object_in_graph(start, graph_name)?
4823                } else {
4824                    look_in_transitive_closure(
4825                        self.eval_from_in_graph(p, start, graph_name),
4826                        move |e| self.eval_from_in_graph(p, &e, graph_name),
4827                        end,
4828                    )?
4829                }
4830            }
4831            PropertyPath::OneOrMore(p) => look_in_transitive_closure(
4832                self.eval_from_in_graph(p, start, graph_name),
4833                move |e| self.eval_from_in_graph(p, &e, graph_name),
4834                end,
4835            )?,
4836            PropertyPath::ZeroOrOne(p) => {
4837                if start == end {
4838                    self.is_subject_or_object_in_graph(start, graph_name)
4839                } else {
4840                    self.eval_closed_in_graph(p, start, end, graph_name)
4841                }?
4842            }
4843            PropertyPath::NegatedPropertySet(ps) => self
4844                .dataset
4845                .internal_quads_for_pattern(Some(start), None, Some(end), Some(graph_name))
4846                .find_map(move |t| match t {
4847                    Ok(t) => {
4848                        if ps.contains(&t.predicate) {
4849                            None
4850                        } else {
4851                            Some(Ok(()))
4852                        }
4853                    }
4854                    Err(e) => Some(Err(e)),
4855                })
4856                .transpose()?
4857                .is_some(),
4858        })
4859    }
4860
4861    fn eval_closed_in_unknown_graph(
4862        &self,
4863        path: &PropertyPath<D>,
4864        start: &D::InternalTerm,
4865        end: &D::InternalTerm,
4866    ) -> Box<dyn Iterator<Item = Result<Option<D::InternalTerm>, QueryEvaluationError>>> {
4867        match path {
4868            PropertyPath::Path(p) => Box::new(
4869                self.dataset
4870                    .internal_quads_for_pattern(Some(start), Some(p), Some(end), None)
4871                    .map(|t| Ok(t?.graph_name)),
4872            ),
4873            PropertyPath::Reverse(p) => self.eval_closed_in_unknown_graph(p, end, start),
4874            PropertyPath::Sequence(a, b) => {
4875                let eval = self.clone();
4876                let b = Rc::clone(b);
4877                let end = end.clone();
4878                Box::new(self.eval_from_in_unknown_graph(a, start).flat_map_ok(
4879                    move |(middle, graph_name)| {
4880                        eval.eval_closed_in_graph(&b, &middle, &end, graph_name.as_ref())
4881                            .map(|is_found| is_found.then_some(graph_name))
4882                            .transpose()
4883                    },
4884                ))
4885            }
4886            PropertyPath::Alternative(a, b) => Box::new(hash_deduplicate(
4887                self.eval_closed_in_unknown_graph(a, start, end)
4888                    .chain(self.eval_closed_in_unknown_graph(b, start, end)),
4889            )),
4890            PropertyPath::ZeroOrMore(p) => {
4891                let eval = self.clone();
4892                let start2 = start.clone();
4893                let end = end.clone();
4894                let p = Rc::clone(p);
4895                self.run_if_term_is_a_dataset_node(start, move |graph_name| {
4896                    look_in_transitive_closure(
4897                        Some(Ok(start2.clone())),
4898                        |e| eval.eval_from_in_graph(&p, &e, graph_name.as_ref()),
4899                        &end,
4900                    )
4901                    .map(|is_found| is_found.then_some(graph_name))
4902                    .transpose()
4903                })
4904            }
4905            PropertyPath::OneOrMore(p) => {
4906                let eval = self.clone();
4907                let end = end.clone();
4908                let p = Rc::clone(p);
4909                Box::new(
4910                    self.eval_from_in_unknown_graph(&p, start)
4911                        .filter_map(move |r| {
4912                            r.and_then(|(start, graph_name)| {
4913                                look_in_transitive_closure(
4914                                    Some(Ok(start)),
4915                                    |e| eval.eval_from_in_graph(&p, &e, graph_name.as_ref()),
4916                                    &end,
4917                                )
4918                                .map(|is_found| is_found.then_some(graph_name))
4919                            })
4920                            .transpose()
4921                        }),
4922                )
4923            }
4924            PropertyPath::ZeroOrOne(p) => {
4925                if start == end {
4926                    self.run_if_term_is_a_dataset_node(start, |graph_name| Some(Ok(graph_name)))
4927                } else {
4928                    let eval = self.clone();
4929                    let start2 = start.clone();
4930                    let end = end.clone();
4931                    let p = Rc::clone(p);
4932                    self.run_if_term_is_a_dataset_node(start, move |graph_name| {
4933                        eval.eval_closed_in_graph(&p, &start2, &end, graph_name.as_ref())
4934                            .map(|is_found| is_found.then_some(graph_name))
4935                            .transpose()
4936                    })
4937                }
4938            }
4939            PropertyPath::NegatedPropertySet(ps) => {
4940                let ps = Rc::clone(ps);
4941                Box::new(
4942                    self.dataset
4943                        .internal_quads_for_pattern(Some(start), None, Some(end), None)
4944                        .filter_map(move |t| match t {
4945                            Ok(t) => {
4946                                if ps.contains(&t.predicate) {
4947                                    None
4948                                } else {
4949                                    Some(Ok(t.graph_name))
4950                                }
4951                            }
4952                            Err(e) => Some(Err(e)),
4953                        }),
4954                )
4955            }
4956        }
4957    }
4958
4959    fn eval_from_in_graph(
4960        &self,
4961        path: &PropertyPath<D>,
4962        start: &D::InternalTerm,
4963        graph_name: Option<&D::InternalTerm>,
4964    ) -> Box<dyn Iterator<Item = Result<D::InternalTerm, QueryEvaluationError>>> {
4965        match path {
4966            PropertyPath::Path(p) => Box::new(
4967                self.dataset
4968                    .internal_quads_for_pattern(Some(start), Some(p), None, Some(graph_name))
4969                    .map(|t| Ok(t?.object)),
4970            ),
4971            PropertyPath::Reverse(p) => self.eval_to_in_graph(p, start, graph_name),
4972            PropertyPath::Sequence(a, b) => {
4973                let eval = self.clone();
4974                let b = Rc::clone(b);
4975                let graph_name2 = graph_name.cloned();
4976                Box::new(
4977                    self.eval_from_in_graph(a, start, graph_name)
4978                        .flat_map_ok(move |middle| {
4979                            eval.eval_from_in_graph(&b, &middle, graph_name2.as_ref())
4980                        }),
4981                )
4982            }
4983            PropertyPath::Alternative(a, b) => Box::new(hash_deduplicate(
4984                self.eval_from_in_graph(a, start, graph_name)
4985                    .chain(self.eval_from_in_graph(b, start, graph_name)),
4986            )),
4987            PropertyPath::ZeroOrMore(p) => {
4988                self.run_if_term_is_a_graph_node(start, graph_name, || {
4989                    let eval = self.clone();
4990                    let p = Rc::clone(p);
4991                    let graph_name2 = graph_name.cloned();
4992                    transitive_closure(Some(Ok(start.clone())), move |e| {
4993                        eval.eval_from_in_graph(&p, &e, graph_name2.as_ref())
4994                    })
4995                })
4996            }
4997            PropertyPath::OneOrMore(p) => {
4998                let eval = self.clone();
4999                let p = Rc::clone(p);
5000                let graph_name2 = graph_name.cloned();
5001                Box::new(transitive_closure(
5002                    self.eval_from_in_graph(&p, start, graph_name),
5003                    move |e| eval.eval_from_in_graph(&p, &e, graph_name2.as_ref()),
5004                ))
5005            }
5006            PropertyPath::ZeroOrOne(p) => {
5007                self.run_if_term_is_a_graph_node(start, graph_name, || {
5008                    hash_deduplicate(
5009                        once(Ok(start.clone()))
5010                            .chain(self.eval_from_in_graph(p, start, graph_name)),
5011                    )
5012                })
5013            }
5014            PropertyPath::NegatedPropertySet(ps) => {
5015                let ps = Rc::clone(ps);
5016                Box::new(
5017                    self.dataset
5018                        .internal_quads_for_pattern(Some(start), None, None, Some(graph_name))
5019                        .filter_map(move |t| match t {
5020                            Ok(t) => {
5021                                if ps.contains(&t.predicate) {
5022                                    None
5023                                } else {
5024                                    Some(Ok(t.object))
5025                                }
5026                            }
5027                            Err(e) => Some(Err(e)),
5028                        }),
5029                )
5030            }
5031        }
5032    }
5033
5034    fn eval_from_in_unknown_graph(
5035        &self,
5036        path: &PropertyPath<D>,
5037        start: &D::InternalTerm,
5038    ) -> Box<
5039        dyn Iterator<
5040            Item = Result<(D::InternalTerm, Option<D::InternalTerm>), QueryEvaluationError>,
5041        >,
5042    > {
5043        match path {
5044            PropertyPath::Path(p) => Box::new(
5045                self.dataset
5046                    .internal_quads_for_pattern(Some(start), Some(p), None, None)
5047                    .map(|t| {
5048                        let t = t?;
5049                        Ok((t.object, t.graph_name))
5050                    }),
5051            ),
5052            PropertyPath::Reverse(p) => self.eval_to_in_unknown_graph(p, start),
5053            PropertyPath::Sequence(a, b) => {
5054                let eval = self.clone();
5055                let b = Rc::clone(b);
5056                Box::new(self.eval_from_in_unknown_graph(a, start).flat_map_ok(
5057                    move |(middle, graph_name)| {
5058                        eval.eval_from_in_graph(&b, &middle, graph_name.as_ref())
5059                            .map(move |end| Ok((end?, graph_name.clone())))
5060                    },
5061                ))
5062            }
5063            PropertyPath::Alternative(a, b) => Box::new(hash_deduplicate(
5064                self.eval_from_in_unknown_graph(a, start)
5065                    .chain(self.eval_from_in_unknown_graph(b, start)),
5066            )),
5067            PropertyPath::ZeroOrMore(p) => {
5068                let start2 = start.clone();
5069                let eval = self.clone();
5070                let p = Rc::clone(p);
5071                self.run_if_term_is_a_dataset_node(start, move |graph_name| {
5072                    let eval = eval.clone();
5073                    let p = Rc::clone(&p);
5074                    let graph_name2 = graph_name.clone();
5075                    transitive_closure(Some(Ok(start2.clone())), move |e| {
5076                        eval.eval_from_in_graph(&p, &e, graph_name2.as_ref())
5077                    })
5078                    .map(move |e| Ok((e?, graph_name.clone())))
5079                })
5080            }
5081            PropertyPath::OneOrMore(p) => {
5082                let eval = self.clone();
5083                let p = Rc::clone(p);
5084                Box::new(transitive_closure(
5085                    self.eval_from_in_unknown_graph(&p, start),
5086                    move |(e, graph_name)| {
5087                        eval.eval_from_in_graph(&p, &e, graph_name.as_ref())
5088                            .map(move |e| Ok((e?, graph_name.clone())))
5089                    },
5090                ))
5091            }
5092            PropertyPath::ZeroOrOne(p) => {
5093                let eval = self.clone();
5094                let start2 = start.clone();
5095                let p = Rc::clone(p);
5096                self.run_if_term_is_a_dataset_node(start, move |graph_name| {
5097                    hash_deduplicate(once(Ok(start2.clone())).chain(eval.eval_from_in_graph(
5098                        &p,
5099                        &start2,
5100                        graph_name.as_ref(),
5101                    )))
5102                    .map(move |e| Ok((e?, graph_name.clone())))
5103                })
5104            }
5105            PropertyPath::NegatedPropertySet(ps) => {
5106                let ps = Rc::clone(ps);
5107                Box::new(
5108                    self.dataset
5109                        .internal_quads_for_pattern(Some(start), None, None, None)
5110                        .filter_map(move |t| match t {
5111                            Ok(t) => {
5112                                if ps.contains(&t.predicate) {
5113                                    None
5114                                } else {
5115                                    Some(Ok((t.object, t.graph_name)))
5116                                }
5117                            }
5118                            Err(e) => Some(Err(e)),
5119                        }),
5120                )
5121            }
5122        }
5123    }
5124
5125    fn eval_to_in_graph(
5126        &self,
5127        path: &PropertyPath<D>,
5128        end: &D::InternalTerm,
5129        graph_name: Option<&D::InternalTerm>,
5130    ) -> Box<dyn Iterator<Item = Result<D::InternalTerm, QueryEvaluationError>>> {
5131        match path {
5132            PropertyPath::Path(p) => Box::new(
5133                self.dataset
5134                    .internal_quads_for_pattern(None, Some(p), Some(end), Some(graph_name))
5135                    .map(|t| Ok(t?.subject)),
5136            ),
5137            PropertyPath::Reverse(p) => self.eval_from_in_graph(p, end, graph_name),
5138            PropertyPath::Sequence(a, b) => {
5139                let eval = self.clone();
5140                let a = Rc::clone(a);
5141                let graph_name2 = graph_name.cloned();
5142                Box::new(
5143                    self.eval_to_in_graph(b, end, graph_name)
5144                        .flat_map_ok(move |middle| {
5145                            eval.eval_to_in_graph(&a, &middle, graph_name2.as_ref())
5146                        }),
5147                )
5148            }
5149            PropertyPath::Alternative(a, b) => Box::new(hash_deduplicate(
5150                self.eval_to_in_graph(a, end, graph_name)
5151                    .chain(self.eval_to_in_graph(b, end, graph_name)),
5152            )),
5153            PropertyPath::ZeroOrMore(p) => {
5154                self.run_if_term_is_a_graph_node(end, graph_name, || {
5155                    let eval = self.clone();
5156                    let p = Rc::clone(p);
5157                    let graph_name2 = graph_name.cloned();
5158                    transitive_closure(Some(Ok(end.clone())), move |e| {
5159                        eval.eval_to_in_graph(&p, &e, graph_name2.as_ref())
5160                    })
5161                })
5162            }
5163            PropertyPath::OneOrMore(p) => {
5164                let eval = self.clone();
5165                let p = Rc::clone(p);
5166                let graph_name2 = graph_name.cloned();
5167                Box::new(transitive_closure(
5168                    self.eval_to_in_graph(&p, end, graph_name),
5169                    move |e| eval.eval_to_in_graph(&p, &e, graph_name2.as_ref()),
5170                ))
5171            }
5172            PropertyPath::ZeroOrOne(p) => self.run_if_term_is_a_graph_node(end, graph_name, || {
5173                hash_deduplicate(
5174                    once(Ok(end.clone())).chain(self.eval_to_in_graph(p, end, graph_name)),
5175                )
5176            }),
5177            PropertyPath::NegatedPropertySet(ps) => {
5178                let ps = Rc::clone(ps);
5179                Box::new(
5180                    self.dataset
5181                        .internal_quads_for_pattern(None, None, Some(end), Some(graph_name))
5182                        .filter_map(move |t| match t {
5183                            Ok(t) => {
5184                                if ps.contains(&t.predicate) {
5185                                    None
5186                                } else {
5187                                    Some(Ok(t.subject))
5188                                }
5189                            }
5190                            Err(e) => Some(Err(e)),
5191                        }),
5192                )
5193            }
5194        }
5195    }
5196
5197    fn eval_to_in_unknown_graph(
5198        &self,
5199        path: &PropertyPath<D>,
5200        end: &D::InternalTerm,
5201    ) -> Box<
5202        dyn Iterator<
5203            Item = Result<(D::InternalTerm, Option<D::InternalTerm>), QueryEvaluationError>,
5204        >,
5205    > {
5206        match path {
5207            PropertyPath::Path(p) => Box::new(
5208                self.dataset
5209                    .internal_quads_for_pattern(None, Some(p), Some(end), None)
5210                    .map(|t| {
5211                        let t = t?;
5212                        Ok((t.subject, t.graph_name))
5213                    }),
5214            ),
5215            PropertyPath::Reverse(p) => self.eval_from_in_unknown_graph(p, end),
5216            PropertyPath::Sequence(a, b) => {
5217                let eval = self.clone();
5218                let a = Rc::clone(a);
5219                Box::new(self.eval_to_in_unknown_graph(b, end).flat_map_ok(
5220                    move |(middle, graph_name)| {
5221                        eval.eval_to_in_graph(&a, &middle, graph_name.as_ref())
5222                            .map(move |start| Ok((start?, graph_name.clone())))
5223                    },
5224                ))
5225            }
5226            PropertyPath::Alternative(a, b) => Box::new(hash_deduplicate(
5227                self.eval_to_in_unknown_graph(a, end)
5228                    .chain(self.eval_to_in_unknown_graph(b, end)),
5229            )),
5230            PropertyPath::ZeroOrMore(p) => {
5231                let end2 = end.clone();
5232                let eval = self.clone();
5233                let p = Rc::clone(p);
5234                self.run_if_term_is_a_dataset_node(end, move |graph_name| {
5235                    let eval = eval.clone();
5236                    let p = Rc::clone(&p);
5237                    let graph_name2 = graph_name.clone();
5238                    transitive_closure(Some(Ok(end2.clone())), move |e| {
5239                        eval.eval_to_in_graph(&p, &e, graph_name2.as_ref())
5240                    })
5241                    .map(move |e| Ok((e?, graph_name.clone())))
5242                })
5243            }
5244            PropertyPath::OneOrMore(p) => {
5245                let eval = self.clone();
5246                let p = Rc::clone(p);
5247                Box::new(transitive_closure(
5248                    self.eval_to_in_unknown_graph(&p, end),
5249                    move |(e, graph_name)| {
5250                        eval.eval_to_in_graph(&p, &e, graph_name.as_ref())
5251                            .map(move |e| Ok((e?, graph_name.clone())))
5252                    },
5253                ))
5254            }
5255            PropertyPath::ZeroOrOne(p) => {
5256                let eval = self.clone();
5257                let end2 = end.clone();
5258                let p = Rc::clone(p);
5259                self.run_if_term_is_a_dataset_node(end, move |graph_name| {
5260                    hash_deduplicate(once(Ok(end2.clone())).chain(eval.eval_to_in_graph(
5261                        &p,
5262                        &end2,
5263                        graph_name.as_ref(),
5264                    )))
5265                    .map(move |e| Ok((e?, graph_name.clone())))
5266                })
5267            }
5268            PropertyPath::NegatedPropertySet(ps) => {
5269                let ps = Rc::clone(ps);
5270                Box::new(
5271                    self.dataset
5272                        .internal_quads_for_pattern(None, None, Some(end), None)
5273                        .filter_map(move |t| match t {
5274                            Ok(t) => {
5275                                if ps.contains(&t.predicate) {
5276                                    None
5277                                } else {
5278                                    Some(Ok((t.subject, t.graph_name)))
5279                                }
5280                            }
5281                            Err(e) => Some(Err(e)),
5282                        }),
5283                )
5284            }
5285        }
5286    }
5287
5288    fn eval_open_in_graph(
5289        &self,
5290        path: &PropertyPath<D>,
5291        graph_name: Option<&D::InternalTerm>,
5292    ) -> Box<dyn Iterator<Item = Result<(D::InternalTerm, D::InternalTerm), QueryEvaluationError>>>
5293    {
5294        match path {
5295            PropertyPath::Path(p) => Box::new(
5296                self.dataset
5297                    .internal_quads_for_pattern(None, Some(p), None, Some(graph_name))
5298                    .map(|t| {
5299                        let t = t?;
5300                        Ok((t.subject, t.object))
5301                    }),
5302            ),
5303            PropertyPath::Reverse(p) => Box::new(
5304                self.eval_open_in_graph(p, graph_name)
5305                    .map(|t| t.map(|(s, o)| (o, s))),
5306            ),
5307            PropertyPath::Sequence(a, b) => {
5308                let eval = self.clone();
5309                let b = Rc::clone(b);
5310                let graph_name2 = graph_name.cloned();
5311                Box::new(self.eval_open_in_graph(a, graph_name).flat_map_ok(
5312                    move |(start, middle)| {
5313                        eval.eval_from_in_graph(&b, &middle, graph_name2.as_ref())
5314                            .map(move |end| Ok((start.clone(), end?)))
5315                    },
5316                ))
5317            }
5318            PropertyPath::Alternative(a, b) => Box::new(hash_deduplicate(
5319                self.eval_open_in_graph(a, graph_name)
5320                    .chain(self.eval_open_in_graph(b, graph_name)),
5321            )),
5322            PropertyPath::ZeroOrMore(p) => {
5323                let eval = self.clone();
5324                let p = Rc::clone(p);
5325                let graph_name2 = graph_name.cloned();
5326                Box::new(transitive_closure(
5327                    self.get_subject_or_object_identity_pairs_in_graph(graph_name),
5328                    move |(start, middle)| {
5329                        eval.eval_from_in_graph(&p, &middle, graph_name2.as_ref())
5330                            .map(move |end| Ok((start.clone(), end?)))
5331                    },
5332                ))
5333            }
5334            PropertyPath::OneOrMore(p) => {
5335                let eval = self.clone();
5336                let p = Rc::clone(p);
5337                let graph_name2 = graph_name.cloned();
5338                Box::new(transitive_closure(
5339                    self.eval_open_in_graph(&p, graph_name),
5340                    move |(start, middle)| {
5341                        eval.eval_from_in_graph(&p, &middle, graph_name2.as_ref())
5342                            .map(move |end| Ok((start.clone(), end?)))
5343                    },
5344                ))
5345            }
5346            PropertyPath::ZeroOrOne(p) => Box::new(hash_deduplicate(
5347                self.get_subject_or_object_identity_pairs_in_graph(graph_name)
5348                    .chain(self.eval_open_in_graph(p, graph_name)),
5349            )),
5350            PropertyPath::NegatedPropertySet(ps) => {
5351                let ps = Rc::clone(ps);
5352                Box::new(
5353                    self.dataset
5354                        .internal_quads_for_pattern(None, None, None, Some(graph_name))
5355                        .filter_map(move |t| match t {
5356                            Ok(t) => {
5357                                if ps.contains(&t.predicate) {
5358                                    None
5359                                } else {
5360                                    Some(Ok((t.subject, t.object)))
5361                                }
5362                            }
5363                            Err(e) => Some(Err(e)),
5364                        }),
5365                )
5366            }
5367        }
5368    }
5369
5370    fn eval_open_in_unknown_graph(
5371        &self,
5372        path: &PropertyPath<D>,
5373    ) -> Box<
5374        dyn Iterator<
5375            Item = Result<
5376                (D::InternalTerm, D::InternalTerm, Option<D::InternalTerm>),
5377                QueryEvaluationError,
5378            >,
5379        >,
5380    > {
5381        match path {
5382            PropertyPath::Path(p) => Box::new(
5383                self.dataset
5384                    .internal_quads_for_pattern(None, Some(p), None, None)
5385                    .map(|t| {
5386                        let t = t?;
5387                        Ok((t.subject, t.object, t.graph_name))
5388                    }),
5389            ),
5390            PropertyPath::Reverse(p) => Box::new(
5391                self.eval_open_in_unknown_graph(p)
5392                    .map(|t| t.map(|(s, o, g)| (o, s, g))),
5393            ),
5394            PropertyPath::Sequence(a, b) => {
5395                let eval = self.clone();
5396                let b = Rc::clone(b);
5397                Box::new(self.eval_open_in_unknown_graph(a).flat_map_ok(
5398                    move |(start, middle, graph_name)| {
5399                        eval.eval_from_in_graph(&b, &middle, graph_name.as_ref())
5400                            .map(move |end| Ok((start.clone(), end?, graph_name.clone())))
5401                    },
5402                ))
5403            }
5404            PropertyPath::Alternative(a, b) => Box::new(hash_deduplicate(
5405                self.eval_open_in_unknown_graph(a)
5406                    .chain(self.eval_open_in_unknown_graph(b)),
5407            )),
5408            PropertyPath::ZeroOrMore(p) => {
5409                let eval = self.clone();
5410                let p = Rc::clone(p);
5411                Box::new(transitive_closure(
5412                    self.get_subject_or_object_identity_pairs_in_dataset(),
5413                    move |(start, middle, graph_name)| {
5414                        eval.eval_from_in_graph(&p, &middle, graph_name.as_ref())
5415                            .map(move |end| Ok((start.clone(), end?, graph_name.clone())))
5416                    },
5417                ))
5418            }
5419            PropertyPath::OneOrMore(p) => {
5420                let eval = self.clone();
5421                let p = Rc::clone(p);
5422                Box::new(transitive_closure(
5423                    self.eval_open_in_unknown_graph(&p),
5424                    move |(start, middle, graph_name)| {
5425                        eval.eval_from_in_graph(&p, &middle, graph_name.as_ref())
5426                            .map(move |end| Ok((start.clone(), end?, graph_name.clone())))
5427                    },
5428                ))
5429            }
5430            PropertyPath::ZeroOrOne(p) => Box::new(hash_deduplicate(
5431                self.get_subject_or_object_identity_pairs_in_dataset()
5432                    .chain(self.eval_open_in_unknown_graph(p)),
5433            )),
5434            PropertyPath::NegatedPropertySet(ps) => {
5435                let ps = Rc::clone(ps);
5436                Box::new(
5437                    self.dataset
5438                        .internal_quads_for_pattern(None, None, None, None)
5439                        .filter_map(move |t| match t {
5440                            Ok(t) => {
5441                                if ps.contains(&t.predicate) {
5442                                    None
5443                                } else {
5444                                    Some(Ok((t.subject, t.object, t.graph_name)))
5445                                }
5446                            }
5447                            Err(e) => Some(Err(e)),
5448                        }),
5449                )
5450            }
5451        }
5452    }
5453
5454    fn get_subject_or_object_identity_pairs_in_graph(
5455        &self,
5456        graph_name: Option<&D::InternalTerm>,
5457    ) -> impl Iterator<Item = Result<(D::InternalTerm, D::InternalTerm), QueryEvaluationError>>
5458    {
5459        self.dataset
5460            .internal_quads_for_pattern(None, None, None, Some(graph_name))
5461            .flat_map_ok(|t| {
5462                [
5463                    Ok((t.subject.clone(), t.subject)),
5464                    Ok((t.object.clone(), t.object)),
5465                ]
5466            })
5467    }
5468
5469    fn get_subject_or_object_identity_pairs_in_dataset(
5470        &self,
5471    ) -> impl Iterator<
5472        Item = Result<
5473            (D::InternalTerm, D::InternalTerm, Option<D::InternalTerm>),
5474            QueryEvaluationError,
5475        >,
5476    > {
5477        self.dataset
5478            .internal_quads_for_pattern(None, None, None, None)
5479            .flat_map_ok(|t| {
5480                [
5481                    Ok((t.subject.clone(), t.subject, t.graph_name.clone())),
5482                    Ok((t.object.clone(), t.object, t.graph_name)),
5483                ]
5484            })
5485    }
5486
5487    fn run_if_term_is_a_graph_node<
5488        T: 'static,
5489        I: Iterator<Item = Result<T, QueryEvaluationError>> + 'static,
5490    >(
5491        &self,
5492        term: &D::InternalTerm,
5493        graph_name: Option<&D::InternalTerm>,
5494        f: impl FnOnce() -> I,
5495    ) -> Box<dyn Iterator<Item = Result<T, QueryEvaluationError>>> {
5496        match self.is_subject_or_object_in_graph(term, graph_name) {
5497            Ok(true) => Box::new(f()),
5498            Ok(false) => {
5499                Box::new(empty()) // Not in the database
5500            }
5501            Err(error) => Box::new(once(Err(error))),
5502        }
5503    }
5504
5505    fn is_subject_or_object_in_graph(
5506        &self,
5507        term: &D::InternalTerm,
5508        graph_name: Option<&D::InternalTerm>,
5509    ) -> Result<bool, QueryEvaluationError> {
5510        Ok(self
5511            .dataset
5512            .internal_quads_for_pattern(Some(term), None, None, Some(graph_name))
5513            .next()
5514            .transpose()?
5515            .is_some()
5516            || self
5517                .dataset
5518                .internal_quads_for_pattern(None, None, Some(term), Some(graph_name))
5519                .next()
5520                .transpose()?
5521                .is_some())
5522    }
5523
5524    fn run_if_term_is_a_dataset_node<
5525        T: 'static,
5526        I: IntoIterator<Item = Result<T, QueryEvaluationError>> + 'static,
5527    >(
5528        &self,
5529        term: &D::InternalTerm,
5530        f: impl FnMut(Option<D::InternalTerm>) -> I + 'static,
5531    ) -> Box<dyn Iterator<Item = Result<T, QueryEvaluationError>>> {
5532        match self
5533            .find_graphs_where_the_node_is_in(term)
5534            .collect::<Result<FxHashSet<_>, _>>()
5535        {
5536            Ok(graph_names) => Box::new(graph_names.into_iter().flat_map(f)),
5537            Err(error) => Box::new(once(Err(error))),
5538        }
5539    }
5540
5541    fn find_graphs_where_the_node_is_in(
5542        &self,
5543        term: &D::InternalTerm,
5544    ) -> impl Iterator<Item = Result<Option<D::InternalTerm>, QueryEvaluationError>> {
5545        self.dataset
5546            .internal_quads_for_pattern(Some(term), None, None, None)
5547            .chain(
5548                self.dataset
5549                    .internal_quads_for_pattern(None, None, Some(term), None),
5550            )
5551            .map(|q| Ok(q?.graph_name))
5552    }
5553}
5554
5555impl<D: QueryableDataset> Clone for PathEvaluator<D> {
5556    fn clone(&self) -> Self {
5557        Self {
5558            dataset: self.dataset.clone(),
5559        }
5560    }
5561}
5562
5563struct CartesianProductJoinIterator<D: QueryableDataset> {
5564    probe_iter: Peekable<InternalTuplesIterator<D>>,
5565    built: Vec<InternalTuple<D>>,
5566    buffered_results: Vec<Result<InternalTuple<D>, QueryEvaluationError>>,
5567}
5568
5569impl<D: QueryableDataset> Iterator for CartesianProductJoinIterator<D> {
5570    type Item = Result<InternalTuple<D>, QueryEvaluationError>;
5571
5572    fn next(&mut self) -> Option<Self::Item> {
5573        loop {
5574            if let Some(result) = self.buffered_results.pop() {
5575                return Some(result);
5576            }
5577            let probe_tuple = match self.probe_iter.next()? {
5578                Ok(probe_tuple) => probe_tuple,
5579                Err(error) => return Some(Err(error)),
5580            };
5581            for built_tuple in &self.built {
5582                if let Some(result_tuple) = probe_tuple.combine_with(built_tuple) {
5583                    self.buffered_results.push(Ok(result_tuple))
5584                }
5585            }
5586        }
5587    }
5588
5589    fn size_hint(&self) -> (usize, Option<usize>) {
5590        let (min, max) = self.probe_iter.size_hint();
5591        (
5592            min.saturating_mul(self.built.len()),
5593            max.map(|v| v.saturating_mul(self.built.len())),
5594        )
5595    }
5596}
5597
5598struct HashJoinIterator<D: QueryableDataset> {
5599    probe_iter: Peekable<InternalTuplesIterator<D>>,
5600    built: InternalTupleSet<D>,
5601    buffered_results: Vec<Result<InternalTuple<D>, QueryEvaluationError>>,
5602}
5603
5604impl<D: QueryableDataset> Iterator for HashJoinIterator<D> {
5605    type Item = Result<InternalTuple<D>, QueryEvaluationError>;
5606
5607    fn next(&mut self) -> Option<Self::Item> {
5608        loop {
5609            if let Some(result) = self.buffered_results.pop() {
5610                return Some(result);
5611            }
5612            let probe_tuple = match self.probe_iter.next()? {
5613                Ok(probe_tuple) => probe_tuple,
5614                Err(error) => return Some(Err(error)),
5615            };
5616            self.buffered_results.extend(
5617                self.built
5618                    .get(&probe_tuple)
5619                    .iter()
5620                    .filter_map(|built_tuple| probe_tuple.combine_with(built_tuple).map(Ok)),
5621            )
5622        }
5623    }
5624
5625    fn size_hint(&self) -> (usize, Option<usize>) {
5626        (
5627            0,
5628            self.probe_iter
5629                .size_hint()
5630                .1
5631                .map(|v| v.saturating_mul(self.built.len())),
5632        )
5633    }
5634}
5635
5636struct HashLeftJoinIterator<D: QueryableDataset> {
5637    left_iter: InternalTuplesIterator<D>,
5638    right: InternalTupleSet<D>,
5639    buffered_results: Vec<Result<InternalTuple<D>, QueryEvaluationError>>,
5640    expression: Rc<dyn Fn(&InternalTuple<D>) -> Option<bool>>,
5641}
5642
5643impl<D: QueryableDataset> Iterator for HashLeftJoinIterator<D> {
5644    type Item = Result<InternalTuple<D>, QueryEvaluationError>;
5645
5646    fn next(&mut self) -> Option<Self::Item> {
5647        loop {
5648            if let Some(result) = self.buffered_results.pop() {
5649                return Some(result);
5650            }
5651            let left_tuple = match self.left_iter.next()? {
5652                Ok(left_tuple) => left_tuple,
5653                Err(error) => return Some(Err(error)),
5654            };
5655            self.buffered_results.extend(
5656                self.right
5657                    .get(&left_tuple)
5658                    .iter()
5659                    .filter_map(|right_tuple| left_tuple.combine_with(right_tuple))
5660                    .filter(|tuple| (self.expression)(tuple).unwrap_or(false))
5661                    .map(Ok),
5662            );
5663            if self.buffered_results.is_empty() {
5664                // We have not manage to join with anything
5665                return Some(Ok(left_tuple));
5666            }
5667        }
5668    }
5669
5670    fn size_hint(&self) -> (usize, Option<usize>) {
5671        (
5672            0,
5673            self.left_iter
5674                .size_hint()
5675                .1
5676                .map(|v| v.saturating_mul(self.right.len())),
5677        )
5678    }
5679}
5680
5681#[cfg(feature = "sep-0006")]
5682struct ForLoopLeftJoinIterator<D: QueryableDataset> {
5683    right_evaluator: Rc<dyn Fn(InternalTuple<D>) -> InternalTuplesIterator<D>>,
5684    left_iter: InternalTuplesIterator<D>,
5685    current_right: InternalTuplesIterator<D>,
5686    left_tuple_to_yield: Option<InternalTuple<D>>,
5687}
5688
5689#[cfg(feature = "sep-0006")]
5690impl<D: QueryableDataset> Iterator for ForLoopLeftJoinIterator<D> {
5691    type Item = Result<InternalTuple<D>, QueryEvaluationError>;
5692
5693    fn next(&mut self) -> Option<Self::Item> {
5694        loop {
5695            if let Some(tuple) = self.current_right.next() {
5696                if tuple.is_ok() {
5697                    // No need to yield left, we have a tuple combined with right
5698                    self.left_tuple_to_yield = None;
5699                }
5700                return Some(tuple);
5701            }
5702            if let Some(left_tuple) = self.left_tuple_to_yield.take() {
5703                return Some(Ok(left_tuple));
5704            }
5705            let left_tuple = match self.left_iter.next()? {
5706                Ok(left_tuple) => left_tuple,
5707                Err(error) => return Some(Err(error)),
5708            };
5709            self.current_right = (self.right_evaluator)(left_tuple.clone());
5710            self.left_tuple_to_yield = Some(left_tuple);
5711        }
5712    }
5713}
5714
5715struct UnionIterator<D: QueryableDataset> {
5716    plans: Vec<Rc<dyn Fn(InternalTuple<D>) -> InternalTuplesIterator<D>>>,
5717    input: InternalTuple<D>,
5718    current_iterator: InternalTuplesIterator<D>,
5719    current_plan: usize,
5720}
5721
5722impl<D: QueryableDataset> Iterator for UnionIterator<D> {
5723    type Item = Result<InternalTuple<D>, QueryEvaluationError>;
5724
5725    fn next(&mut self) -> Option<Self::Item> {
5726        loop {
5727            if let Some(tuple) = self.current_iterator.next() {
5728                return Some(tuple);
5729            }
5730            if self.current_plan >= self.plans.len() {
5731                return None;
5732            }
5733            self.current_iterator = self.plans[self.current_plan](self.input.clone());
5734            self.current_plan += 1;
5735        }
5736    }
5737}
5738
5739struct ConsecutiveDeduplication<D: QueryableDataset> {
5740    inner: InternalTuplesIterator<D>,
5741    current: Option<InternalTuple<D>>,
5742}
5743
5744impl<D: QueryableDataset> Iterator for ConsecutiveDeduplication<D> {
5745    type Item = Result<InternalTuple<D>, QueryEvaluationError>;
5746
5747    fn next(&mut self) -> Option<Self::Item> {
5748        // Basic idea. We buffer the previous result and we only emit it when we know the next one or it's the end
5749        loop {
5750            if let Some(next) = self.inner.next() {
5751                match next {
5752                    Ok(next) => match self.current.take() {
5753                        Some(current) if current != next => {
5754                            // We found a relevant value
5755                            self.current = Some(next);
5756                            return Some(Ok(current));
5757                        }
5758                        _ => {
5759                            //  We discard the value and move to the next one
5760                            self.current = Some(next);
5761                        }
5762                    },
5763                    Err(error) => return Some(Err(error)), // We swap but it's fine. It's an error.
5764                }
5765            } else {
5766                return self.current.take().map(Ok);
5767            }
5768        }
5769    }
5770
5771    fn size_hint(&self) -> (usize, Option<usize>) {
5772        let (min, max) = self.inner.size_hint();
5773        ((min != 0).into(), max)
5774    }
5775}
5776
5777struct ConstructIterator<D: QueryableDataset> {
5778    eval: SimpleEvaluator<D>,
5779    iter: InternalTuplesIterator<D>,
5780    template: Vec<TripleTemplate>,
5781    buffered_results: Vec<Result<Triple, QueryEvaluationError>>,
5782    already_emitted_results: FxHashSet<Triple>,
5783    bnodes: Vec<BlankNode>,
5784}
5785
5786impl<D: QueryableDataset> Iterator for ConstructIterator<D> {
5787    type Item = Result<Triple, QueryEvaluationError>;
5788
5789    fn next(&mut self) -> Option<Self::Item> {
5790        loop {
5791            if let Some(result) = self.buffered_results.pop() {
5792                return Some(result);
5793            }
5794            {
5795                let tuple = match self.iter.next()? {
5796                    Ok(tuple) => tuple,
5797                    Err(error) => return Some(Err(error)),
5798                };
5799                for template in &self.template {
5800                    if let (Some(subject), Some(predicate), Some(object)) = (
5801                        get_triple_template_value(
5802                            &template.subject,
5803                            &tuple,
5804                            &mut self.bnodes,
5805                            &self.eval.dataset,
5806                        )
5807                        .and_then(|t| t.try_into().ok()),
5808                        get_triple_template_value(
5809                            &template.predicate,
5810                            &tuple,
5811                            &mut self.bnodes,
5812                            &self.eval.dataset,
5813                        )
5814                        .and_then(|t| t.try_into().ok()),
5815                        get_triple_template_value(
5816                            &template.object,
5817                            &tuple,
5818                            &mut self.bnodes,
5819                            &self.eval.dataset,
5820                        ),
5821                    ) {
5822                        let triple = Triple {
5823                            subject,
5824                            predicate,
5825                            object,
5826                        };
5827                        // We allocate new blank nodes for each solution,
5828                        // triples with blank nodes are likely to be new.
5829                        #[cfg(feature = "rdf-star")]
5830                        let new_triple = triple.subject.is_blank_node()
5831                            || triple.subject.is_triple()
5832                            || triple.object.is_blank_node()
5833                            || triple.object.is_triple()
5834                            || self.already_emitted_results.insert(triple.clone());
5835                        #[cfg(not(feature = "rdf-star"))]
5836                        let new_triple = triple.subject.is_blank_node()
5837                            || triple.object.is_blank_node()
5838                            || self.already_emitted_results.insert(triple.clone());
5839                        if new_triple {
5840                            self.buffered_results.push(Ok(triple));
5841                            if self.already_emitted_results.len() > 1024 * 1024 {
5842                                // We don't want to have a too big memory impact
5843                                self.already_emitted_results.clear();
5844                            }
5845                        }
5846                    }
5847                }
5848                self.bnodes.clear(); // We do not reuse blank nodes
5849            }
5850        }
5851    }
5852
5853    fn size_hint(&self) -> (usize, Option<usize>) {
5854        let (min, max) = self.iter.size_hint();
5855        (
5856            min.saturating_mul(self.template.len()),
5857            max.map(|v| v.saturating_mul(self.template.len())),
5858        )
5859    }
5860}
5861
5862pub struct TripleTemplate {
5863    pub subject: TripleTemplateValue,
5864    pub predicate: TripleTemplateValue,
5865    pub object: TripleTemplateValue,
5866}
5867
5868pub enum TripleTemplateValue {
5869    Constant(Term),
5870    BlankNode(usize),
5871    Variable(usize),
5872    #[cfg(feature = "rdf-star")]
5873    Triple(Box<TripleTemplate>),
5874}
5875
5876impl TripleTemplateValue {
5877    #[cfg_attr(not(feature = "rdf-star"), allow(clippy::unnecessary_wraps))]
5878    fn from_term_or_variable(
5879        term_or_variable: &TermPattern,
5880        variables: &mut Vec<Variable>,
5881        bnodes: &mut Vec<BlankNode>,
5882    ) -> Option<Self> {
5883        Some(match term_or_variable {
5884            TermPattern::Variable(variable) => Self::Variable(encode_variable(variables, variable)),
5885            TermPattern::NamedNode(node) => Self::Constant(node.clone().into()),
5886            TermPattern::BlankNode(bnode) => Self::BlankNode(bnode_key(bnodes, bnode)),
5887            TermPattern::Literal(literal) => Self::Constant(literal.clone().into()),
5888            #[cfg(feature = "rdf-star")]
5889            TermPattern::Triple(triple) => {
5890                match (
5891                    Self::from_term_or_variable(&triple.subject, variables, bnodes)?,
5892                    Self::from_named_node_or_variable(&triple.predicate, variables),
5893                    Self::from_term_or_variable(&triple.object, variables, bnodes)?,
5894                ) {
5895                    (
5896                        Self::Constant(subject),
5897                        Self::Constant(predicate),
5898                        Self::Constant(object),
5899                    ) => Self::Constant(
5900                        Triple {
5901                            subject: subject.try_into().ok()?,
5902                            predicate: predicate.try_into().ok()?,
5903                            object,
5904                        }
5905                        .into(),
5906                    ),
5907                    (subject, predicate, object) => {
5908                        TripleTemplateValue::Triple(Box::new(TripleTemplate {
5909                            subject,
5910                            predicate,
5911                            object,
5912                        }))
5913                    }
5914                }
5915            }
5916        })
5917    }
5918
5919    fn from_named_node_or_variable(
5920        named_node_or_variable: &NamedNodePattern,
5921        variables: &mut Vec<Variable>,
5922    ) -> TripleTemplateValue {
5923        match named_node_or_variable {
5924            NamedNodePattern::Variable(variable) => {
5925                Self::Variable(encode_variable(variables, variable))
5926            }
5927            NamedNodePattern::NamedNode(term) => Self::Constant(term.clone().into()),
5928        }
5929    }
5930}
5931
5932fn get_triple_template_value<D: QueryableDataset>(
5933    selector: &TripleTemplateValue,
5934    tuple: &InternalTuple<D>,
5935    bnodes: &mut Vec<BlankNode>,
5936    dataset: &EvalDataset<D>,
5937) -> Option<Term> {
5938    match selector {
5939        TripleTemplateValue::Constant(term) => Some(term.clone()),
5940        TripleTemplateValue::Variable(v) => {
5941            tuple
5942                .get(*v)
5943                .and_then(|t| dataset.externalize_term(t.clone()).ok()) // TODO: raise error
5944        }
5945        TripleTemplateValue::BlankNode(bnode) => {
5946            if *bnode >= bnodes.len() {
5947                bnodes.resize_with(*bnode + 1, BlankNode::default)
5948            }
5949            Some(bnodes[*bnode].clone().into())
5950        }
5951        #[cfg(feature = "rdf-star")]
5952        TripleTemplateValue::Triple(triple) => Some(
5953            Triple {
5954                subject: get_triple_template_value(&triple.subject, tuple, bnodes, dataset)?
5955                    .try_into()
5956                    .ok()?,
5957                predicate: get_triple_template_value(&triple.predicate, tuple, bnodes, dataset)?
5958                    .try_into()
5959                    .ok()?,
5960                object: get_triple_template_value(&triple.object, tuple, bnodes, dataset)?,
5961            }
5962            .into(),
5963        ),
5964    }
5965}
5966
5967struct DescribeIterator<D: QueryableDataset> {
5968    eval: SimpleEvaluator<D>,
5969    tuples_to_describe: InternalTuplesIterator<D>,
5970    nodes_described: FxHashSet<D::InternalTerm>,
5971    nodes_to_describe: Vec<D::InternalTerm>,
5972    quads: Box<dyn Iterator<Item = Result<InternalQuad<D>, QueryEvaluationError>>>,
5973}
5974
5975impl<D: QueryableDataset> Iterator for DescribeIterator<D> {
5976    type Item = Result<Triple, QueryEvaluationError>;
5977
5978    fn next(&mut self) -> Option<Self::Item> {
5979        loop {
5980            if let Some(quad) = self.quads.next() {
5981                let quad = match quad {
5982                    Ok(quad) => quad,
5983                    Err(error) => return Some(Err(error)),
5984                };
5985                // We yield the triple
5986                let subject = match self.eval.dataset.externalize_term(quad.subject) {
5987                    Ok(t) => t,
5988                    Err(e) => return Some(Err(e)),
5989                };
5990                let predicate = match self.eval.dataset.externalize_term(quad.predicate) {
5991                    Ok(t) => t,
5992                    Err(e) => return Some(Err(e)),
5993                };
5994                let object = match self.eval.dataset.externalize_term(quad.object.clone()) {
5995                    Ok(t) => t,
5996                    Err(e) => return Some(Err(e)),
5997                };
5998                // If there is a blank node object, we need to describe it too
5999                if object.is_blank_node() && self.nodes_described.insert(quad.object.clone()) {
6000                    self.nodes_to_describe.push(quad.object);
6001                }
6002                return Some(Ok(Triple {
6003                    subject: subject.try_into().ok()?,
6004                    predicate: predicate.try_into().ok()?,
6005                    object,
6006                }));
6007            }
6008            if let Some(node_to_describe) = self.nodes_to_describe.pop() {
6009                // We have a new node to describe
6010                self.quads = Box::new(self.eval.dataset.internal_quads_for_pattern(
6011                    Some(&node_to_describe),
6012                    None,
6013                    None,
6014                    Some(None),
6015                ));
6016            } else {
6017                let tuple = match self.tuples_to_describe.next()? {
6018                    Ok(tuple) => tuple,
6019                    Err(error) => return Some(Err(error)),
6020                };
6021                for node in tuple.into_iter().flatten() {
6022                    if self.nodes_described.insert(node.clone()) {
6023                        self.nodes_to_describe.push(node);
6024                    }
6025                }
6026            }
6027        }
6028    }
6029}
6030
6031struct ZipLongest<T1, T2, I1: Iterator<Item = T1>, I2: Iterator<Item = T2>> {
6032    a: I1,
6033    b: I2,
6034}
6035
6036impl<T1, T2, I1: Iterator<Item = T1>, I2: Iterator<Item = T2>> ZipLongest<T1, T2, I1, I2> {
6037    fn new(a: I1, b: I2) -> Self {
6038        Self { a, b }
6039    }
6040}
6041
6042impl<T1, T2, I1: Iterator<Item = T1>, I2: Iterator<Item = T2>> Iterator
6043    for ZipLongest<T1, T2, I1, I2>
6044{
6045    type Item = (Option<T1>, Option<T2>);
6046
6047    fn next(&mut self) -> Option<Self::Item> {
6048        match (self.a.next(), self.b.next()) {
6049            (None, None) => None,
6050            r => Some(r),
6051        }
6052    }
6053}
6054
6055fn transitive_closure<T: Clone + Eq + Hash, E, NI: Iterator<Item = Result<T, E>>>(
6056    start: impl IntoIterator<Item = Result<T, E>>,
6057    mut next: impl FnMut(T) -> NI,
6058) -> impl Iterator<Item = Result<T, E>> {
6059    let mut errors = Vec::new();
6060    let mut todo = start
6061        .into_iter()
6062        .filter_map(|e| match e {
6063            Ok(e) => Some(e),
6064            Err(e) => {
6065                errors.push(e);
6066                None
6067            }
6068        })
6069        .collect::<Vec<_>>();
6070    let mut all = todo.iter().cloned().collect::<FxHashSet<_>>();
6071    while let Some(e) = todo.pop() {
6072        for e in next(e) {
6073            match e {
6074                Ok(e) => {
6075                    if all.insert(e.clone()) {
6076                        todo.push(e)
6077                    }
6078                }
6079                Err(e) => errors.push(e),
6080            }
6081        }
6082    }
6083    errors.into_iter().map(Err).chain(all.into_iter().map(Ok))
6084}
6085
6086fn look_in_transitive_closure<T: Clone + Eq + Hash, E, NI: Iterator<Item = Result<T, E>>>(
6087    start: impl IntoIterator<Item = Result<T, E>>,
6088    mut next: impl FnMut(T) -> NI,
6089    target: &T,
6090) -> Result<bool, E> {
6091    let mut todo = start.into_iter().collect::<Result<Vec<_>, _>>()?;
6092    let mut all = todo.iter().cloned().collect::<FxHashSet<_>>();
6093    while let Some(e) = todo.pop() {
6094        if e == *target {
6095            return Ok(true);
6096        }
6097        for e in next(e) {
6098            let e = e?;
6099            if all.insert(e.clone()) {
6100                todo.push(e);
6101            }
6102        }
6103    }
6104    Ok(false)
6105}
6106
6107fn hash_deduplicate<T: Eq + Hash + Clone, E>(
6108    iter: impl Iterator<Item = Result<T, E>>,
6109) -> impl Iterator<Item = Result<T, E>> {
6110    let mut already_seen = FxHashSet::with_capacity_and_hasher(iter.size_hint().0, FxBuildHasher);
6111    iter.filter(move |e| {
6112        if let Ok(e) = e {
6113            if already_seen.contains(e) {
6114                false
6115            } else {
6116                already_seen.insert(e.clone());
6117                true
6118            }
6119        } else {
6120            true
6121        }
6122    })
6123}
6124
6125trait ResultIterator<T, E>: Iterator<Item = Result<T, E>> + Sized {
6126    fn flat_map_ok<O, F: FnMut(T) -> U, U: IntoIterator<Item = Result<O, E>>>(
6127        self,
6128        f: F,
6129    ) -> FlatMapOk<T, E, O, Self, F, U>;
6130}
6131
6132impl<T, E, I: Iterator<Item = Result<T, E>> + Sized> ResultIterator<T, E> for I {
6133    #[inline]
6134    fn flat_map_ok<O, F: FnMut(T) -> U, U: IntoIterator<Item = Result<O, E>>>(
6135        self,
6136        f: F,
6137    ) -> FlatMapOk<T, E, O, Self, F, U> {
6138        FlatMapOk {
6139            inner: self,
6140            f,
6141            current: None,
6142        }
6143    }
6144}
6145
6146struct FlatMapOk<
6147    T,
6148    E,
6149    O,
6150    I: Iterator<Item = Result<T, E>>,
6151    F: FnMut(T) -> U,
6152    U: IntoIterator<Item = Result<O, E>>,
6153> {
6154    inner: I,
6155    f: F,
6156    current: Option<U::IntoIter>,
6157}
6158
6159impl<
6160        T,
6161        E,
6162        O,
6163        I: Iterator<Item = Result<T, E>>,
6164        F: FnMut(T) -> U,
6165        U: IntoIterator<Item = Result<O, E>>,
6166    > Iterator for FlatMapOk<T, E, O, I, F, U>
6167{
6168    type Item = Result<O, E>;
6169
6170    #[inline]
6171    fn next(&mut self) -> Option<Self::Item> {
6172        loop {
6173            if let Some(current) = &mut self.current {
6174                if let Some(next) = current.next() {
6175                    return Some(next);
6176                }
6177            }
6178            self.current = None;
6179            match self.inner.next()? {
6180                Ok(e) => self.current = Some((self.f)(e).into_iter()),
6181                Err(error) => return Some(Err(error)),
6182            }
6183        }
6184    }
6185}
6186
6187fn generate_uuid(buffer: &mut String) {
6188    let mut uuid = random::<u128>().to_le_bytes();
6189    uuid[6] = (uuid[6] & 0x0F) | 0x40;
6190    uuid[8] = (uuid[8] & 0x3F) | 0x80;
6191
6192    write_hexa_bytes(&uuid[0..4], buffer);
6193    buffer.push('-');
6194    write_hexa_bytes(&uuid[4..6], buffer);
6195    buffer.push('-');
6196    write_hexa_bytes(&uuid[6..8], buffer);
6197    buffer.push('-');
6198    write_hexa_bytes(&uuid[8..10], buffer);
6199    buffer.push('-');
6200    write_hexa_bytes(&uuid[10..16], buffer);
6201}
6202
6203fn write_hexa_bytes(bytes: &[u8], buffer: &mut String) {
6204    for b in bytes {
6205        let high = b / 16;
6206        buffer.push(char::from(if high < 10 {
6207            b'0' + high
6208        } else {
6209            b'a' + (high - 10)
6210        }));
6211        let low = b % 16;
6212        buffer.push(char::from(if low < 10 {
6213            b'0' + low
6214        } else {
6215            b'a' + (low - 10)
6216        }));
6217    }
6218}
6219
6220fn error_evaluator<D: QueryableDataset>(
6221    error: QueryEvaluationError,
6222) -> Rc<dyn Fn(InternalTuple<D>) -> InternalTuplesIterator<D>> {
6223    let e = RefCell::new(Some(error));
6224    Rc::new(move |_| {
6225        if let Some(e) = e.replace(None) {
6226            Box::new(once(Err(e)))
6227        } else {
6228            Box::new(empty())
6229        }
6230    })
6231}
6232
6233enum ComparatorFunction<D: QueryableDataset> {
6234    Asc(Rc<dyn Fn(&InternalTuple<D>) -> Option<ExpressionTerm>>),
6235    Desc(Rc<dyn Fn(&InternalTuple<D>) -> Option<ExpressionTerm>>),
6236}
6237
6238struct InternalTupleSet<D: QueryableDataset> {
6239    key: Vec<usize>,
6240    map: FxHashMap<u64, Vec<InternalTuple<D>>>,
6241    len: usize,
6242}
6243
6244impl<D: QueryableDataset> InternalTupleSet<D> {
6245    fn new(key: Vec<usize>) -> Self {
6246        Self {
6247            key,
6248            map: FxHashMap::default(),
6249            len: 0,
6250        }
6251    }
6252
6253    fn insert(&mut self, tuple: InternalTuple<D>) {
6254        self.map
6255            .entry(self.tuple_key(&tuple))
6256            .or_default()
6257            .push(tuple);
6258        self.len += 1;
6259    }
6260
6261    fn get(&self, tuple: &InternalTuple<D>) -> &[InternalTuple<D>] {
6262        self.map.get(&self.tuple_key(tuple)).map_or(&[], |v| v)
6263    }
6264
6265    fn tuple_key(&self, tuple: &InternalTuple<D>) -> u64 {
6266        let mut hasher = FxHasher::default();
6267        for v in &self.key {
6268            if let Some(val) = tuple.get(*v) {
6269                val.hash(&mut hasher);
6270            }
6271        }
6272        hasher.finish()
6273    }
6274
6275    fn len(&self) -> usize {
6276        self.len
6277    }
6278
6279    fn is_empty(&self) -> bool {
6280        self.len == 0
6281    }
6282}
6283
6284impl<D: QueryableDataset> Extend<InternalTuple<D>> for InternalTupleSet<D> {
6285    fn extend<T: IntoIterator<Item = InternalTuple<D>>>(&mut self, iter: T) {
6286        let iter = iter.into_iter();
6287        self.map.reserve(iter.size_hint().0);
6288        for tuple in iter {
6289            self.insert(tuple);
6290        }
6291    }
6292}
6293
6294struct StatsIterator<D: QueryableDataset> {
6295    inner: InternalTuplesIterator<D>,
6296    stats: Rc<EvalNodeWithStats>,
6297}
6298
6299impl<D: QueryableDataset> Iterator for StatsIterator<D> {
6300    type Item = Result<InternalTuple<D>, QueryEvaluationError>;
6301
6302    fn next(&mut self) -> Option<Self::Item> {
6303        let start = Timer::now();
6304        let result = self.inner.next();
6305        let duration = start.elapsed()?;
6306        self.stats.exec_duration.set(
6307            self.stats
6308                .exec_duration
6309                .get()
6310                .and_then(|d| d.checked_add(duration)),
6311        );
6312        if matches!(result, Some(Ok(_))) {
6313            self.stats.exec_count.set(self.stats.exec_count.get() + 1);
6314        }
6315        result
6316    }
6317}
6318
6319pub struct EvalNodeWithStats {
6320    pub label: String,
6321    pub children: Vec<Rc<EvalNodeWithStats>>,
6322    pub exec_count: Cell<usize>,
6323    pub exec_duration: Cell<Option<DayTimeDuration>>,
6324}
6325
6326impl EvalNodeWithStats {
6327    pub fn json_node(
6328        &self,
6329        serializer: &mut WriterJsonSerializer<impl io::Write>,
6330        with_stats: bool,
6331    ) -> io::Result<()> {
6332        serializer.serialize_event(JsonEvent::StartObject)?;
6333        serializer.serialize_event(JsonEvent::ObjectKey("name".into()))?;
6334        serializer.serialize_event(JsonEvent::String((&self.label).into()))?;
6335        if with_stats {
6336            serializer.serialize_event(JsonEvent::ObjectKey("number of results".into()))?;
6337            serializer
6338                .serialize_event(JsonEvent::Number(self.exec_count.get().to_string().into()))?;
6339            if let Some(duration) = self.exec_duration.get() {
6340                serializer.serialize_event(JsonEvent::ObjectKey("duration in seconds".into()))?;
6341                serializer
6342                    .serialize_event(JsonEvent::Number(duration.as_seconds().to_string().into()))?;
6343            }
6344        }
6345        serializer.serialize_event(JsonEvent::ObjectKey("children".into()))?;
6346        serializer.serialize_event(JsonEvent::StartArray)?;
6347        for child in &self.children {
6348            child.json_node(serializer, with_stats)?;
6349        }
6350        serializer.serialize_event(JsonEvent::EndArray)?;
6351        serializer.serialize_event(JsonEvent::EndObject)
6352    }
6353}
6354
6355impl fmt::Debug for EvalNodeWithStats {
6356    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6357        let mut obj = f.debug_struct("Node");
6358        obj.field("name", &self.label);
6359        if let Some(exec_duration) = self.exec_duration.get() {
6360            obj.field("number of results", &self.exec_count.get());
6361            obj.field(
6362                "duration in seconds",
6363                &f32::from(Float::from(exec_duration.as_seconds())),
6364            );
6365        }
6366        if !self.children.is_empty() {
6367            obj.field("children", &self.children);
6368        }
6369        obj.finish()
6370    }
6371}
6372
6373fn eval_node_label(node: &GraphPattern) -> String {
6374    match node {
6375        GraphPattern::Distinct { .. } => "Distinct(Hash)".to_owned(),
6376        GraphPattern::Extend {
6377            expression,
6378            variable,
6379            ..
6380        } => format!(
6381            "Extend({} -> {variable})",
6382            spargebra::algebra::Expression::from(expression)
6383        ),
6384        GraphPattern::Filter { expression, .. } => format!(
6385            "Filter({})",
6386            spargebra::algebra::Expression::from(expression)
6387        ),
6388        GraphPattern::Graph { graph_name } => format!("Graph({graph_name})"),
6389        GraphPattern::Group {
6390            variables,
6391            aggregates,
6392            ..
6393        } => {
6394            format!(
6395                "Aggregate({})",
6396                format_list(variables.iter().map(ToString::to_string).chain(
6397                    aggregates.iter().map(|(v, agg)| format!(
6398                        "{} -> {v}",
6399                        spargebra::algebra::AggregateExpression::from(agg)
6400                    ))
6401                ))
6402            )
6403        }
6404        GraphPattern::Join { algorithm, .. } => match algorithm {
6405            JoinAlgorithm::HashBuildLeftProbeRight { keys } => format!(
6406                "LeftJoin(HashBuildLeftProbeRight, keys = {})",
6407                format_list(keys)
6408            ),
6409        },
6410        #[cfg(feature = "sep-0006")]
6411        GraphPattern::Lateral { right, .. } => {
6412            if let GraphPattern::LeftJoin {
6413                left: nested_left,
6414                expression,
6415                ..
6416            } = right.as_ref()
6417            {
6418                if nested_left.is_empty_singleton() {
6419                    // We are in a ForLoopLeftJoin
6420                    return format!(
6421                        "ForLoopLeftJoin(expression = {})",
6422                        spargebra::algebra::Expression::from(expression)
6423                    );
6424                }
6425            }
6426            "Lateral".to_owned()
6427        }
6428        GraphPattern::LeftJoin {
6429            algorithm,
6430            expression,
6431            ..
6432        } => match algorithm {
6433            LeftJoinAlgorithm::HashBuildRightProbeLeft { keys } => format!(
6434                "LeftJoin(HashBuildRightProbeLeft, keys = {}, expression = {})",
6435                format_list(keys),
6436                spargebra::algebra::Expression::from(expression)
6437            ),
6438        },
6439        GraphPattern::Minus { algorithm, .. } => match algorithm {
6440            MinusAlgorithm::HashBuildRightProbeLeft { keys } => format!(
6441                "AntiJoin(HashBuildRightProbeLeft, keys = {})",
6442                format_list(keys)
6443            ),
6444        },
6445        GraphPattern::OrderBy { expression, .. } => {
6446            format!(
6447                "Sort({})",
6448                format_list(
6449                    expression
6450                        .iter()
6451                        .map(spargebra::algebra::OrderExpression::from)
6452                )
6453            )
6454        }
6455        GraphPattern::Path {
6456            subject,
6457            path,
6458            object,
6459            graph_name,
6460        } => {
6461            if let Some(graph_name) = graph_name {
6462                format!("Path({subject} {path} {object} {graph_name})")
6463            } else {
6464                format!("Path({subject} {path} {object})")
6465            }
6466        }
6467        GraphPattern::Project { variables, .. } => {
6468            format!("Project({})", format_list(variables))
6469        }
6470        GraphPattern::QuadPattern {
6471            subject,
6472            predicate,
6473            object,
6474            graph_name,
6475        } => {
6476            if let Some(graph_name) = graph_name {
6477                format!("QuadPattern({subject} {predicate} {object} {graph_name})")
6478            } else {
6479                format!("QuadPattern({subject} {predicate} {object})")
6480            }
6481        }
6482        GraphPattern::Reduced { .. } => "Reduced".to_owned(),
6483        GraphPattern::Service { name, silent, .. } => {
6484            if *silent {
6485                format!("Service({name}, Silent)")
6486            } else {
6487                format!("Service({name})")
6488            }
6489        }
6490        GraphPattern::Slice { start, length, .. } => {
6491            if let Some(length) = length {
6492                format!("Slice(start = {start}, length = {length})")
6493            } else {
6494                format!("Slice(start = {start})")
6495            }
6496        }
6497        GraphPattern::Union { .. } => "Union".to_owned(),
6498        GraphPattern::Values { variables, .. } => {
6499            format!("StaticBindings({})", format_list(variables))
6500        }
6501    }
6502}
6503
6504fn format_list<T: ToString>(values: impl IntoIterator<Item = T>) -> String {
6505    values
6506        .into_iter()
6507        .map(|v| v.to_string())
6508        .collect::<Vec<_>>()
6509        .join(", ")
6510}
6511
6512pub struct Timer {
6513    start: DateTime,
6514}
6515
6516impl Timer {
6517    pub fn now() -> Self {
6518        Self {
6519            start: DateTime::now(),
6520        }
6521    }
6522
6523    pub fn elapsed(&self) -> Option<DayTimeDuration> {
6524        DateTime::now().checked_sub(self.start)
6525    }
6526}
6527
6528#[cfg(test)]
6529mod tests {
6530    use super::*;
6531
6532    #[test]
6533    fn uuid() {
6534        let mut buffer = String::default();
6535        generate_uuid(&mut buffer);
6536        assert!(
6537            Regex::new("^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$")
6538                .unwrap()
6539                .is_match(&buffer),
6540            "{buffer} is not a valid UUID"
6541        );
6542    }
6543}