Fork of https://github.com/oxigraph/oxigraph.git for the purpose of NextGraph project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
oxigraph/lib/src/sparql/mod.rs

151 lines
5.0 KiB

//! [SPARQL](https://www.w3.org/TR/sparql11-overview/) implementation.
//!
//! Stores execute SPARQL. See [`MemoryStore`](super::store::memory::MemoryStore::query()) for an example.
mod algebra;
mod csv_results;
mod dataset;
mod error;
mod eval;
mod http;
mod json_results;
mod model;
mod parser;
mod plan;
mod plan_builder;
mod service;
mod update;
mod xml_results;
use crate::sparql::algebra::QueryVariants;
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};
pub use crate::sparql::parser::ParseError;
use crate::sparql::plan_builder::PlanBuilder;
pub use crate::sparql::service::ServiceHandler;
4 years ago
use crate::sparql::service::{EmptyServiceHandler, ErrorConversionServiceHandler};
use crate::sparql::update::SimpleUpdateEvaluator;
use crate::store::numeric_encoder::StrContainer;
use crate::store::{ReadableEncodedStore, StoreOrParseError, WritableEncodedStore};
use std::convert::TryInto;
use std::io;
use std::rc::Rc;
pub(crate) fn evaluate_query<R: ReadableEncodedStore + 'static>(
store: R,
query: impl TryInto<Query, Error = impl Into<EvaluationError>>,
options: QueryOptions,
) -> Result<QueryResults, EvaluationError> {
match query.try_into().map_err(|e| e.into())?.0 {
QueryVariants::Select {
algebra,
base_iri,
dataset,
} => {
let dataset = DatasetView::new(store, &dataset)?;
let (plan, variables) = PlanBuilder::build(&dataset, &algebra)?;
SimpleEvaluator::new(Rc::new(dataset), base_iri, options.service_handler)
.evaluate_select_plan(&plan, Rc::new(variables))
}
QueryVariants::Ask {
algebra,
base_iri,
dataset,
} => {
let dataset = DatasetView::new(store, &dataset)?;
let (plan, _) = PlanBuilder::build(&dataset, &algebra)?;
SimpleEvaluator::new(Rc::new(dataset), base_iri, options.service_handler)
.evaluate_ask_plan(&plan)
}
QueryVariants::Construct {
construct,
algebra,
base_iri,
dataset,
} => {
let dataset = DatasetView::new(store, &dataset)?;
let (plan, variables) = PlanBuilder::build(&dataset, &algebra)?;
let construct = PlanBuilder::build_graph_template(&dataset, &construct, variables)?;
SimpleEvaluator::new(Rc::new(dataset), base_iri, options.service_handler)
.evaluate_construct_plan(&plan, construct)
}
QueryVariants::Describe {
algebra,
base_iri,
dataset,
} => {
let dataset = DatasetView::new(store, &dataset)?;
let (plan, _) = PlanBuilder::build(&dataset, &algebra)?;
SimpleEvaluator::new(Rc::new(dataset), base_iri, 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<dyn ServiceHandler<Error = EvaluationError>>,
}
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
}
5 years ago
/// Disables the `SERVICE` calls
#[inline]
pub fn without_service_handler(mut self) -> Self {
self.service_handler = Rc::new(EmptyServiceHandler);
self
5 years ago
}
}
pub(crate) fn evaluate_update<
R: ReadableEncodedStore + Clone + 'static,
W: StrContainer<StrId = R::StrId> + WritableEncodedStore<StrId = R::StrId>,
>(
read: R,
write: &mut W,
update: &Update,
) -> Result<(), EvaluationError>
where
io::Error: From<StoreOrParseError<W::Error>>,
{
SimpleUpdateEvaluator::new(
read,
write,
update.base_iri.clone(),
Rc::new(EmptyServiceHandler),
)
.eval_all(&update.operations)
}