1mod algebra;
6mod dataset;
7mod error;
8mod http;
9mod model;
10pub mod results;
11mod service;
12mod update;
13
14use crate::model::{NamedNode, Term};
15pub use crate::sparql::algebra::{Query, QueryDataset, Update};
16use crate::sparql::dataset::DatasetView;
17pub use crate::sparql::error::EvaluationError;
18pub use crate::sparql::model::{QueryResults, QuerySolution, QuerySolutionIter, QueryTripleIter};
19pub use crate::sparql::service::ServiceHandler;
20use crate::sparql::service::{EmptyServiceHandler, WrappedDefaultServiceHandler};
21pub(crate) use crate::sparql::update::evaluate_update;
22use crate::storage::StorageReader;
23pub use oxrdf::{Variable, VariableNameParseError};
24use spareval::QueryEvaluator;
25pub use spareval::QueryExplanation;
26pub use spargebra::SparqlSyntaxError;
27use std::time::Duration;
28
29#[allow(clippy::needless_pass_by_value)]
30pub(crate) fn evaluate_query(
31 reader: StorageReader,
32 query: impl TryInto<Query, Error = impl Into<EvaluationError>>,
33 options: QueryOptions,
34 run_stats: bool,
35 substitutions: impl IntoIterator<Item = (Variable, Term)>,
36) -> Result<(Result<QueryResults, EvaluationError>, QueryExplanation), EvaluationError> {
37 let query = query.try_into().map_err(Into::into)?;
38 let dataset = DatasetView::new(reader, &query.dataset);
39 let mut evaluator = options.into_evaluator();
40 if run_stats {
41 evaluator = evaluator.compute_statistics();
42 }
43 let (results, explanation) =
44 evaluator.explain_with_substituted_variables(dataset, &query.inner, substitutions);
45 let results = results.map_err(Into::into).map(Into::into);
46 Ok((results, explanation))
47}
48
49#[derive(Clone)]
68pub struct QueryOptions {
69 http_timeout: Option<Duration>,
70 http_redirection_limit: usize,
71 inner: QueryEvaluator,
72}
73
74impl QueryOptions {
75 #[inline]
77 #[must_use]
78 pub fn with_service_handler(mut self, service_handler: impl ServiceHandler + 'static) -> Self {
79 self.inner = self
80 .inner
81 .with_default_service_handler(WrappedDefaultServiceHandler(service_handler));
82 self
83 }
84
85 #[inline]
87 #[must_use]
88 pub fn without_service_handler(mut self) -> Self {
89 self.inner = self.inner.with_default_service_handler(EmptyServiceHandler);
90 self
91 }
92
93 #[cfg(feature = "http-client")]
95 #[inline]
96 #[must_use]
97 pub fn with_http_timeout(mut self, timeout: Duration) -> Self {
98 self.http_timeout = Some(timeout);
99 self
100 }
101
102 #[cfg(feature = "http-client")]
106 #[inline]
107 #[must_use]
108 pub fn with_http_redirection_limit(mut self, redirection_limit: usize) -> Self {
109 self.http_redirection_limit = redirection_limit;
110 self
111 }
112
113 fn into_evaluator(mut self) -> QueryEvaluator {
114 if !self.inner.has_default_service_handler() {
115 self.inner =
116 self.inner
117 .with_default_service_handler(service::SimpleServiceHandler::new(
118 self.http_timeout,
119 self.http_redirection_limit,
120 ))
121 }
122 self.inner
123 }
124
125 #[inline]
150 #[must_use]
151 pub fn with_custom_function(
152 mut self,
153 name: NamedNode,
154 evaluator: impl Fn(&[Term]) -> Option<Term> + Send + Sync + 'static,
155 ) -> Self {
156 self.inner = self.inner.with_custom_function(name, evaluator);
157 self
158 }
159
160 #[doc(hidden)]
161 #[inline]
162 #[must_use]
163 pub fn without_optimizations(mut self) -> Self {
164 self.inner = self.inner.without_optimizations();
165 self
166 }
167}
168
169impl Default for QueryOptions {
170 fn default() -> Self {
171 let mut options = Self {
172 http_timeout: None,
173 http_redirection_limit: 0,
174 inner: QueryEvaluator::new(),
175 };
176 if cfg!(feature = "http-client") {
177 options.inner =
178 options
179 .inner
180 .with_default_service_handler(service::SimpleServiceHandler::new(
181 options.http_timeout,
182 options.http_redirection_limit,
183 ));
184 }
185 options
186 }
187}
188
189#[derive(Clone, Default)]
191pub struct UpdateOptions {
192 query_options: QueryOptions,
193}
194
195impl From<QueryOptions> for UpdateOptions {
196 #[inline]
197 fn from(query_options: QueryOptions) -> Self {
198 Self { query_options }
199 }
200}