spareval/
model.rs

1use crate::error::QueryEvaluationError;
2use oxrdf::{Triple, Variable};
3pub use sparesults::QuerySolution;
4use std::sync::Arc;
5
6/// Results of a [SPARQL query](https://www.w3.org/TR/sparql11-query/).
7pub enum QueryResults {
8    /// Results of a [SELECT](https://www.w3.org/TR/sparql11-query/#select) query.
9    Solutions(QuerySolutionIter),
10    /// Result of a [ASK](https://www.w3.org/TR/sparql11-query/#ask) query.
11    Boolean(bool),
12    /// Results of a [CONSTRUCT](https://www.w3.org/TR/sparql11-query/#construct) or [DESCRIBE](https://www.w3.org/TR/sparql11-query/#describe) query.
13    Graph(QueryTripleIter),
14}
15
16impl From<QuerySolutionIter> for QueryResults {
17    #[inline]
18    fn from(value: QuerySolutionIter) -> Self {
19        Self::Solutions(value)
20    }
21}
22
23/// An iterator over [`QuerySolution`]s.
24///
25/// ```
26/// use oxrdf::Dataset;
27/// use spareval::{QueryEvaluator, QueryResults};
28/// use spargebra::Query;
29///
30/// let query = Query::parse("SELECT ?s ?o WHERE { ?s ?p ?o }", None)?;
31/// if let QueryResults::Solutions(solutions) =
32///     QueryEvaluator::new().execute(Dataset::new(), &query)?
33/// {
34///     for solution in solutions {
35///         println!("{:?}", solution?.get("s"));
36///     }
37/// }
38/// # Result::<_, Box<dyn std::error::Error>>::Ok(())
39/// ```
40pub struct QuerySolutionIter {
41    variables: Arc<[Variable]>,
42    iter: Box<dyn Iterator<Item = Result<QuerySolution, QueryEvaluationError>>>,
43}
44
45impl QuerySolutionIter {
46    /// Construct a new iterator of solution from an ordered list of solution variables and an iterator of solution tuples
47    /// (each tuple using the same ordering as the variable list such that tuple element 0 is the value for the variable 0...)
48    pub fn new(
49        variables: Arc<[Variable]>,
50        iter: impl Iterator<Item = Result<QuerySolution, QueryEvaluationError>> + 'static,
51    ) -> Self {
52        Self {
53            variables,
54            iter: Box::new(iter),
55        }
56    }
57
58    /// The variables used in the solutions.
59    ///
60    /// ```
61    /// use oxrdf::{Dataset, Variable};
62    /// use spareval::{QueryEvaluator, QueryResults};
63    /// use spargebra::Query;
64    ///
65    /// let query = Query::parse("SELECT ?s ?o WHERE { ?s ?p ?o }", None)?;
66    /// if let QueryResults::Solutions(solutions) =
67    ///     QueryEvaluator::new().execute(Dataset::new(), &query)?
68    /// {
69    ///     assert_eq!(
70    ///         solutions.variables(),
71    ///         &[Variable::new("s")?, Variable::new("o")?]
72    ///     );
73    /// }
74    /// # Result::<_, Box<dyn std::error::Error>>::Ok(())
75    /// ```
76    #[inline]
77    pub fn variables(&self) -> &[Variable] {
78        &self.variables
79    }
80}
81
82impl Iterator for QuerySolutionIter {
83    type Item = Result<QuerySolution, QueryEvaluationError>;
84
85    #[inline]
86    fn next(&mut self) -> Option<Self::Item> {
87        self.iter.next()
88    }
89
90    #[inline]
91    fn size_hint(&self) -> (usize, Option<usize>) {
92        self.iter.size_hint()
93    }
94}
95
96/// An iterator over the triples that compose a graph solution.
97///
98/// ```
99/// use oxrdf::Dataset;
100/// use spareval::{QueryEvaluator, QueryResults};
101/// use spargebra::Query;
102///
103/// let query = Query::parse("CONSTRUCT WHERE { ?s ?p ?o }", None)?;
104/// if let QueryResults::Graph(triples) = QueryEvaluator::new().execute(Dataset::new(), &query)? {
105///     for triple in triples {
106///         println!("{}", triple?);
107///     }
108/// }
109/// # Result::<_, Box<dyn std::error::Error>>::Ok(())
110/// ```
111pub struct QueryTripleIter {
112    iter: Box<dyn Iterator<Item = Result<Triple, QueryEvaluationError>>>,
113}
114
115impl QueryTripleIter {
116    pub(crate) fn new(
117        iter: impl Iterator<Item = Result<Triple, QueryEvaluationError>> + 'static,
118    ) -> Self {
119        Self {
120            iter: Box::new(iter),
121        }
122    }
123}
124
125impl Iterator for QueryTripleIter {
126    type Item = Result<Triple, QueryEvaluationError>;
127
128    #[inline]
129    fn next(&mut self) -> Option<Self::Item> {
130        self.iter.next()
131    }
132
133    #[inline]
134    fn size_hint(&self) -> (usize, Option<usize>) {
135        self.iter.size_hint()
136    }
137}