//! [SPARQL](https://www.w3.org/TR/sparql11-overview/) implementation. //! //! Stores execute SPARQL. See [`SledStore`](super::store::sled::SledStore::query()) for an example. mod algebra; mod csv_results; mod dataset; mod error; mod eval; mod http; mod json_results; mod model; mod plan; mod plan_builder; mod service; mod update; mod xml_results; pub use crate::sparql::algebra::{Query, Update}; use crate::sparql::dataset::DatasetView; pub use crate::sparql::error::EvaluationError; use crate::sparql::eval::SimpleEvaluator; pub use crate::sparql::model::QueryResults; pub use crate::sparql::model::QueryResultsFormat; pub use crate::sparql::model::QuerySolution; pub use crate::sparql::model::QuerySolutionIter; pub use crate::sparql::model::QueryTripleIter; pub use crate::sparql::model::{Variable, VariableNameParseError}; use crate::sparql::plan_builder::PlanBuilder; pub use crate::sparql::service::ServiceHandler; use crate::sparql::service::{EmptyServiceHandler, ErrorConversionServiceHandler}; use crate::sparql::update::SimpleUpdateEvaluator; use crate::store::numeric_encoder::StrContainer; use crate::store::{ReadableEncodedStore, StoreOrParseError, WritableEncodedStore}; pub use spargebra::ParseError; use std::convert::TryInto; use std::io; use std::rc::Rc; pub(crate) fn evaluate_query( store: R, query: impl TryInto>, options: QueryOptions, ) -> Result { let query = query.try_into().map_err(|e| e.into())?; let dataset = DatasetView::new(store, &query.dataset)?; match query.inner { spargebra::Query::Select { pattern, base_iri, .. } => { let (plan, variables) = PlanBuilder::build(&dataset, &pattern)?; SimpleEvaluator::new( Rc::new(dataset), base_iri.map(Rc::new), options.service_handler, ) .evaluate_select_plan( &plan, Rc::new( variables .into_iter() .map(|v| Variable::new_unchecked(v.name)) .collect(), ), ) } spargebra::Query::Ask { pattern, base_iri, .. } => { let (plan, _) = PlanBuilder::build(&dataset, &pattern)?; SimpleEvaluator::new( Rc::new(dataset), base_iri.map(Rc::new), options.service_handler, ) .evaluate_ask_plan(&plan) } spargebra::Query::Construct { template, pattern, base_iri, .. } => { let (plan, variables) = PlanBuilder::build(&dataset, &pattern)?; let construct = PlanBuilder::build_graph_template(&dataset, &template, variables)?; SimpleEvaluator::new( Rc::new(dataset), base_iri.map(Rc::new), options.service_handler, ) .evaluate_construct_plan(&plan, construct) } spargebra::Query::Describe { pattern, base_iri, .. } => { let (plan, _) = PlanBuilder::build(&dataset, &pattern)?; SimpleEvaluator::new( Rc::new(dataset), base_iri.map(Rc::new), options.service_handler, ) .evaluate_describe_plan(&plan) } } } /// Options for SPARQL query evaluation. /// /// /// If the `"http_client"` optional feature is enabled, /// a simple HTTP 1.1 client is used to execute [SPARQL 1.1 Federated Query](https://www.w3.org/TR/sparql11-federated-query/) SERVICE calls. #[derive(Clone)] pub struct QueryOptions { pub(crate) service_handler: Rc>, } impl Default for QueryOptions { #[inline] fn default() -> Self { Self { service_handler: if cfg!(feature = "http_client") { Rc::new(service::SimpleServiceHandler::new()) } else { Rc::new(EmptyServiceHandler) }, } } } impl QueryOptions { /// Use a given [`ServiceHandler`] to execute [SPARQL 1.1 Federated Query](https://www.w3.org/TR/sparql11-federated-query/) SERVICE calls. #[inline] pub fn with_service_handler(mut self, service_handler: impl ServiceHandler + 'static) -> Self { self.service_handler = Rc::new(ErrorConversionServiceHandler::wrap(service_handler)); self } /// Disables the `SERVICE` calls #[inline] pub fn without_service_handler(mut self) -> Self { self.service_handler = Rc::new(EmptyServiceHandler); self } } /// Options for SPARQL update evaluation #[derive(Clone)] pub struct UpdateOptions { query_options: QueryOptions, } impl UpdateOptions { /// The options related to the querying part of the updates #[inline] pub fn query_options(&self) -> &QueryOptions { &self.query_options } /// The options related to the querying part of the updates #[inline] pub fn query_options_mut(&mut self) -> &mut QueryOptions { &mut self.query_options } } impl Default for UpdateOptions { #[inline] fn default() -> Self { Self { query_options: QueryOptions::default(), } } } impl From for UpdateOptions { #[inline] fn from(query_options: QueryOptions) -> Self { Self { query_options } } } pub(crate) fn evaluate_update< R: ReadableEncodedStore + Clone + 'static, W: StrContainer + WritableEncodedStore, >( read: R, write: &mut W, update: Update, options: UpdateOptions, ) -> Result<(), EvaluationError> where io::Error: From>, { SimpleUpdateEvaluator::new(read, write, update.inner.base_iri.map(Rc::new), options) .eval_all(&update.inner.operations, &update.using_datasets) }