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

185 lines
5.7 KiB

//! [SPARQL](https://www.w3.org/TR/sparql11-overview/) implementation.
mod algebra;
mod eval;
mod json_results;
mod model;
mod parser;
mod plan;
mod plan_builder;
mod xml_results;
use crate::sparql::algebra::QueryVariants;
use crate::sparql::eval::SimpleEvaluator;
use crate::sparql::parser::read_sparql_query;
use crate::sparql::plan::TripleTemplate;
use crate::sparql::plan::{DatasetView, PlanNode};
use crate::sparql::plan_builder::PlanBuilder;
use crate::store::StoreConnection;
use crate::Result;
use std::fmt;
pub use crate::sparql::model::BindingsIterator;
pub use crate::sparql::model::QueryResult;
pub use crate::sparql::model::QueryResultSyntax;
pub use crate::sparql::model::Variable;
/// A prepared [SPARQL query](https://www.w3.org/TR/sparql11-query/)
pub trait PreparedQuery {
/// Evaluates the query and returns its results
fn exec(&self) -> Result<QueryResult>;
}
/// An implementation of `PreparedQuery` for internal use
pub struct SimplePreparedQuery<S: StoreConnection>(SimplePreparedQueryAction<S>);
enum SimplePreparedQueryAction<S: StoreConnection> {
Select {
plan: PlanNode,
variables: Vec<Variable>,
evaluator: SimpleEvaluator<S>,
},
Ask {
plan: PlanNode,
evaluator: SimpleEvaluator<S>,
},
Construct {
plan: PlanNode,
construct: Vec<TripleTemplate>,
evaluator: SimpleEvaluator<S>,
},
Describe {
plan: PlanNode,
evaluator: SimpleEvaluator<S>,
},
}
impl<S: StoreConnection> SimplePreparedQuery<S> {
pub(crate) fn new(connection: S, query: &str, options: QueryOptions) -> Result<Self> {
let dataset = DatasetView::new(connection, options.default_graph_as_union);
//TODO avoid inserting terms in the Repository StringStore
Ok(Self(match read_sparql_query(query, options.base_iri)? {
QueryVariants::Select {
algebra,
dataset: _,
base_iri,
} => {
let (plan, variables) = PlanBuilder::build(dataset.encoder(), &algebra)?;
SimplePreparedQueryAction::Select {
plan,
variables,
evaluator: SimpleEvaluator::new(dataset, base_iri),
}
}
QueryVariants::Ask {
algebra,
dataset: _,
base_iri,
} => {
let (plan, _) = PlanBuilder::build(dataset.encoder(), &algebra)?;
SimplePreparedQueryAction::Ask {
plan,
evaluator: SimpleEvaluator::new(dataset, base_iri),
}
}
QueryVariants::Construct {
construct,
algebra,
dataset: _,
base_iri,
} => {
let (plan, variables) = PlanBuilder::build(dataset.encoder(), &algebra)?;
SimplePreparedQueryAction::Construct {
plan,
construct: PlanBuilder::build_graph_template(
dataset.encoder(),
&construct,
variables,
)?,
evaluator: SimpleEvaluator::new(dataset, base_iri),
}
}
QueryVariants::Describe {
algebra,
dataset: _,
base_iri,
} => {
let (plan, _) = PlanBuilder::build(dataset.encoder(), &algebra)?;
SimplePreparedQueryAction::Describe {
plan,
evaluator: SimpleEvaluator::new(dataset, base_iri),
}
}
}))
}
}
impl<S: StoreConnection> PreparedQuery for SimplePreparedQuery<S> {
fn exec(&self) -> Result<QueryResult<'_>> {
match &self.0 {
SimplePreparedQueryAction::Select {
plan,
variables,
evaluator,
} => evaluator.evaluate_select_plan(&plan, &variables),
SimplePreparedQueryAction::Ask { plan, evaluator } => {
evaluator.evaluate_ask_plan(&plan)
}
SimplePreparedQueryAction::Construct {
plan,
construct,
evaluator,
} => evaluator.evaluate_construct_plan(&plan, &construct),
SimplePreparedQueryAction::Describe { plan, evaluator } => {
evaluator.evaluate_describe_plan(&plan)
}
}
}
}
/// Options for SPARQL query parsing and evaluation like the query base IRI
pub struct QueryOptions<'a> {
pub(crate) base_iri: Option<&'a str>,
pub(crate) default_graph_as_union: bool,
}
impl<'a> Default for QueryOptions<'a> {
fn default() -> Self {
Self {
base_iri: None,
default_graph_as_union: false,
}
}
}
impl<'a> QueryOptions<'a> {
/// Allows to set the base IRI of the query
pub fn with_base_iri(mut self, base_iri: &'a str) -> Self {
self.base_iri = Some(base_iri);
self
}
/// Consider the union of all graphs in the repository as the default graph
pub fn with_default_graph_as_union(mut self) -> Self {
self.default_graph_as_union = true;
self
}
}
/// A parsed [SPARQL query](https://www.w3.org/TR/sparql11-query/)
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct Query(QueryVariants);
impl fmt::Display for Query {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl Query {
/// Parses a SPARQL query
pub fn parse(query: &str, base_iri: Option<&str>) -> Result<Self> {
Ok(Query(read_sparql_query(query, base_iri)?))
}
}