|
|
|
@ -1,5 +1,27 @@ |
|
|
|
|
//! SPARQL 1.1 implementation.
|
|
|
|
|
//! This is a work in progress!!!
|
|
|
|
|
//! [SPARQL](https://www.w3.org/TR/sparql11-overview/) implementation.
|
|
|
|
|
//!
|
|
|
|
|
//! The support of RDF Dataset and SPARQL 1.1 specific features is not done yet.
|
|
|
|
|
//!
|
|
|
|
|
//! This module adds query capabilities to the `rudf::model::Dataset` implementations.
|
|
|
|
|
//!
|
|
|
|
|
//! Usage example:
|
|
|
|
|
//! ```
|
|
|
|
|
//! use rudf::model::*;
|
|
|
|
|
//! use rudf::store::MemoryDataset;
|
|
|
|
|
//! use rudf::sparql::SparqlDataset;
|
|
|
|
|
//! use rudf::sparql::PreparedQuery;
|
|
|
|
|
//! use rudf::sparql::algebra::QueryResult;
|
|
|
|
|
//! use std::str::FromStr;
|
|
|
|
|
//!
|
|
|
|
|
//! let dataset = MemoryDataset::default();
|
|
|
|
|
//! let ex = NamedNode::from_str("http://example.com").unwrap();
|
|
|
|
|
//! dataset.insert(&Quad::new(ex.clone(), ex.clone(), ex.clone(), None));
|
|
|
|
|
//! let prepared_query = dataset.prepare_query("SELECT ?s WHERE { ?s ?p ?o }".as_bytes()).unwrap();
|
|
|
|
|
//! let results = prepared_query.exec().unwrap();
|
|
|
|
|
//! if let QueryResult::Bindings(results) = results {
|
|
|
|
|
//! assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into()));
|
|
|
|
|
//! }
|
|
|
|
|
//! ```
|
|
|
|
|
|
|
|
|
|
use model::Dataset; |
|
|
|
|
use sparql::algebra::Query; |
|
|
|
@ -21,12 +43,21 @@ pub mod parser; |
|
|
|
|
mod plan; |
|
|
|
|
pub mod xml_results; |
|
|
|
|
|
|
|
|
|
/// An extension of the `rudf::model::Dataset` trait to allow SPARQL operations on it.
|
|
|
|
|
///
|
|
|
|
|
/// It is implemented by all stores provided by Rudf
|
|
|
|
|
pub trait SparqlDataset: Dataset { |
|
|
|
|
type PreparedQuery: PreparedQuery; |
|
|
|
|
|
|
|
|
|
/// Prepares a [SPARQL 1.1](https://www.w3.org/TR/sparql11-query/) query and returns an object that could be used to execute it
|
|
|
|
|
///
|
|
|
|
|
/// The implementation is a work in progress, RDF Dataset and SPARQL 1.1 specific features are not implemented yet.
|
|
|
|
|
fn prepare_query(&self, query: impl Read) -> Result<Self::PreparedQuery>; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// A prepared [SPARQL 1.1](https://www.w3.org/TR/sparql11-query/) query
|
|
|
|
|
pub trait PreparedQuery { |
|
|
|
|
/// Evaluates the query and returns its results
|
|
|
|
|
fn exec(&self) -> Result<QueryResult>; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -34,11 +65,11 @@ impl<S: EncodedQuadsStore> SparqlDataset for StoreDataset<S> { |
|
|
|
|
type PreparedQuery = SimplePreparedQuery<S>; |
|
|
|
|
|
|
|
|
|
fn prepare_query(&self, query: impl Read) -> Result<SimplePreparedQuery<S>> { |
|
|
|
|
Ok(match read_sparql_query(query, None)? { |
|
|
|
|
Ok(SimplePreparedQuery(match read_sparql_query(query, None)? { |
|
|
|
|
Query::Select { algebra, dataset } => { |
|
|
|
|
let store = self.encoded(); |
|
|
|
|
let (plan, variables) = PlanBuilder::build(&*store, &algebra)?; |
|
|
|
|
SimplePreparedQuery::Select { |
|
|
|
|
SimplePreparedQueryOptions::Select { |
|
|
|
|
plan, |
|
|
|
|
variables, |
|
|
|
|
evaluator: SimpleEvaluator::new(store), |
|
|
|
@ -47,7 +78,7 @@ impl<S: EncodedQuadsStore> SparqlDataset for StoreDataset<S> { |
|
|
|
|
Query::Ask { algebra, dataset } => { |
|
|
|
|
let store = self.encoded(); |
|
|
|
|
let (plan, _) = PlanBuilder::build(&*store, &algebra)?; |
|
|
|
|
SimplePreparedQuery::Ask { |
|
|
|
|
SimplePreparedQueryOptions::Ask { |
|
|
|
|
plan, |
|
|
|
|
evaluator: SimpleEvaluator::new(store), |
|
|
|
|
} |
|
|
|
@ -59,7 +90,7 @@ impl<S: EncodedQuadsStore> SparqlDataset for StoreDataset<S> { |
|
|
|
|
} => { |
|
|
|
|
let store = self.encoded(); |
|
|
|
|
let (plan, variables) = PlanBuilder::build(&*store, &algebra)?; |
|
|
|
|
SimplePreparedQuery::Construct { |
|
|
|
|
SimplePreparedQueryOptions::Construct { |
|
|
|
|
plan, |
|
|
|
|
construct: PlanBuilder::build_graph_template(&*store, &construct, variables)?, |
|
|
|
|
evaluator: SimpleEvaluator::new(store), |
|
|
|
@ -68,16 +99,19 @@ impl<S: EncodedQuadsStore> SparqlDataset for StoreDataset<S> { |
|
|
|
|
Query::Describe { algebra, dataset } => { |
|
|
|
|
let store = self.encoded(); |
|
|
|
|
let (plan, _) = PlanBuilder::build(&*store, &algebra)?; |
|
|
|
|
SimplePreparedQuery::Describe { |
|
|
|
|
SimplePreparedQueryOptions::Describe { |
|
|
|
|
plan, |
|
|
|
|
evaluator: SimpleEvaluator::new(store), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
})) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub enum SimplePreparedQuery<S: EncodedQuadsStore> { |
|
|
|
|
/// An implementation of `PreparedQuery` for internal use
|
|
|
|
|
pub struct SimplePreparedQuery<S: EncodedQuadsStore>(SimplePreparedQueryOptions<S>); |
|
|
|
|
|
|
|
|
|
enum SimplePreparedQueryOptions<S: EncodedQuadsStore> { |
|
|
|
|
Select { |
|
|
|
|
plan: PlanNode, |
|
|
|
|
variables: Vec<Variable>, |
|
|
|
@ -100,19 +134,21 @@ pub enum SimplePreparedQuery<S: EncodedQuadsStore> { |
|
|
|
|
|
|
|
|
|
impl<S: EncodedQuadsStore> PreparedQuery for SimplePreparedQuery<S> { |
|
|
|
|
fn exec(&self) -> Result<QueryResult> { |
|
|
|
|
match self { |
|
|
|
|
SimplePreparedQuery::Select { |
|
|
|
|
match &self.0 { |
|
|
|
|
SimplePreparedQueryOptions::Select { |
|
|
|
|
plan, |
|
|
|
|
variables, |
|
|
|
|
evaluator, |
|
|
|
|
} => evaluator.evaluate_select_plan(&plan, &variables), |
|
|
|
|
SimplePreparedQuery::Ask { plan, evaluator } => evaluator.evaluate_ask_plan(&plan), |
|
|
|
|
SimplePreparedQuery::Construct { |
|
|
|
|
SimplePreparedQueryOptions::Ask { plan, evaluator } => { |
|
|
|
|
evaluator.evaluate_ask_plan(&plan) |
|
|
|
|
} |
|
|
|
|
SimplePreparedQueryOptions::Construct { |
|
|
|
|
plan, |
|
|
|
|
construct, |
|
|
|
|
evaluator, |
|
|
|
|
} => evaluator.evaluate_construct_plan(&plan, &construct), |
|
|
|
|
SimplePreparedQuery::Describe { plan, evaluator } => { |
|
|
|
|
SimplePreparedQueryOptions::Describe { plan, evaluator } => { |
|
|
|
|
evaluator.evaluate_describe_plan(&plan) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|