Adds FROM and FROM named evaluation

pull/46/head
Tpt 4 years ago
parent 58a3b34d9f
commit bf430de125
  1. 2
      README.md
  2. 4
      lib/src/sparql/algebra.rs
  3. 89
      lib/src/sparql/dataset.rs
  4. 37
      lib/src/sparql/mod.rs
  5. 4
      testsuite/tests/sparql.rs

@ -21,7 +21,7 @@ It is split into multiple parts:
* The `wikibase` directory contains a stand-alone binary of a web server able to synchronize with a [Wikibase instance](https://wikiba.se/).
Are currently implemented:
* [SPARQL 1.1 Query](https://www.w3.org/TR/sparql11-query/) except `FROM` and `FROM NAMED`.
* [SPARQL 1.1 Query](https://www.w3.org/TR/sparql11-query/).
* [SPARQL 1.1 Federated Query](https://www.w3.org/TR/sparql11-federated-query/).
* [Turtle](https://www.w3.org/TR/turtle/), [TriG](https://www.w3.org/TR/trig/), [N-Triples](https://www.w3.org/TR/n-triples/), [N-Quads](https://www.w3.org/TR/n-quads/) and [RDF XML](https://www.w3.org/TR/rdf-syntax-grammar/) RDF serialization formats for both data ingestion and retrieval using the [Rio library](https://github.com/oxigraph/rio).
* [SPARQL Query Results XML Format](http://www.w3.org/TR/rdf-sparql-XMLres/) and [SPARQL Query Results JSON Format](https://www.w3.org/TR/sparql11-results-json/).

@ -1286,6 +1286,10 @@ impl DatasetSpec {
named: vec![graph],
}
}
pub fn is_empty(&self) -> bool {
self.default.is_empty() && self.named.is_empty()
}
}
impl Add for DatasetSpec {

@ -1,6 +1,7 @@
use crate::sparql::algebra::DatasetSpec;
use crate::sparql::EvaluationError;
use crate::store::numeric_encoder::{
EncodedQuad, EncodedTerm, StrContainer, StrId, StrLookup, WithStoreError,
EncodedQuad, EncodedTerm, ReadEncoder, StrContainer, StrId, StrLookup, WithStoreError,
};
use crate::store::ReadableEncodedStore;
use lasso::{Rodeo, Spur};
@ -11,15 +12,39 @@ pub(crate) struct DatasetView<S: ReadableEncodedStore> {
store: S,
extra: RefCell<Rodeo>,
default_graph_as_union: bool,
dataset: Option<EncodedDatasetSpec<S::StrId>>,
}
impl<S: ReadableEncodedStore> DatasetView<S> {
pub fn new(store: S, default_graph_as_union: bool) -> Self {
Self {
pub fn new(
store: S,
default_graph_as_union: bool,
dataset: &DatasetSpec,
) -> Result<Self, EvaluationError> {
let dataset = if dataset.is_empty() {
None
} else {
Some(EncodedDatasetSpec {
default: dataset
.default
.iter()
.flat_map(|g| store.get_encoded_named_node(g.as_ref()).transpose())
.collect::<Result<Vec<_>, _>>()
.map_err(|e| e.into())?,
named: dataset
.named
.iter()
.flat_map(|g| store.get_encoded_named_node(g.as_ref()).transpose())
.collect::<Result<Vec<_>, _>>()
.map_err(|e| e.into())?,
})
};
Ok(Self {
store,
extra: RefCell::new(Rodeo::default()),
default_graph_as_union,
}
dataset,
})
}
}
@ -66,7 +91,56 @@ impl<S: ReadableEncodedStore> ReadableEncodedStore for DatasetView<S> {
if let Some((subject, predicate, object, graph_name)) =
try_map_quad_pattern(subject, predicate, object, graph_name)
{
if graph_name == None {
if let Some(dataset) = &self.dataset {
if let Some(graph_name) = graph_name {
if graph_name == EncodedTerm::DefaultGraph {
let iters = dataset
.default
.iter()
.map(|graph_name| {
self.store.encoded_quads_for_pattern(
subject,
predicate,
object,
Some(*graph_name),
)
})
.collect::<Vec<_>>();
Box::new(map_iter(iters.into_iter().flatten()).map(|quad| {
let quad = quad?;
Ok(EncodedQuad::new(
quad.subject,
quad.predicate,
quad.object,
EncodedTerm::DefaultGraph,
))
}))
} else if dataset.named.contains(&graph_name) {
Box::new(map_iter(self.store.encoded_quads_for_pattern(
subject,
predicate,
object,
Some(graph_name),
)))
} else {
Box::new(empty())
}
} else {
let iters = dataset
.named
.iter()
.map(|graph_name| {
self.store.encoded_quads_for_pattern(
subject,
predicate,
object,
Some(*graph_name),
)
})
.collect::<Vec<_>>();
Box::new(map_iter(iters.into_iter().flatten()))
}
} else if graph_name == None {
Box::new(
map_iter(
self.store
@ -173,3 +247,8 @@ pub enum DatasetStrId<I: StrId> {
}
impl<I: StrId> StrId for DatasetStrId<I> {}
struct EncodedDatasetSpec<I: StrId> {
default: Vec<EncodedTerm<I>>,
named: Vec<EncodedTerm<I>>,
}

@ -75,11 +75,17 @@ impl<S: ReadableEncodedStore + 'static> SimplePreparedQuery<S> {
query: impl TryInto<Query, Error = impl Into<EvaluationError>>,
options: QueryOptions,
) -> Result<Self, EvaluationError> {
let dataset = Rc::new(DatasetView::new(store, options.default_graph_as_union));
Ok(Self(match query.try_into().map_err(|e| e.into())?.0 {
QueryVariants::Select {
algebra, base_iri, ..
algebra,
base_iri,
dataset,
} => {
let dataset = Rc::new(DatasetView::new(
store,
options.default_graph_as_union,
&dataset,
)?);
let (plan, variables) = PlanBuilder::build(dataset.as_ref(), &algebra)?;
SimplePreparedQueryAction::Select {
plan: Rc::new(plan),
@ -88,8 +94,15 @@ impl<S: ReadableEncodedStore + 'static> SimplePreparedQuery<S> {
}
}
QueryVariants::Ask {
algebra, base_iri, ..
algebra,
base_iri,
dataset,
} => {
let dataset = Rc::new(DatasetView::new(
store,
options.default_graph_as_union,
&dataset,
)?);
let (plan, _) = PlanBuilder::build(dataset.as_ref(), &algebra)?;
SimplePreparedQueryAction::Ask {
plan: Rc::new(plan),
@ -100,8 +113,13 @@ impl<S: ReadableEncodedStore + 'static> SimplePreparedQuery<S> {
construct,
algebra,
base_iri,
..
dataset,
} => {
let dataset = Rc::new(DatasetView::new(
store,
options.default_graph_as_union,
&dataset,
)?);
let (plan, variables) = PlanBuilder::build(dataset.as_ref(), &algebra)?;
SimplePreparedQueryAction::Construct {
plan: Rc::new(plan),
@ -114,8 +132,15 @@ impl<S: ReadableEncodedStore + 'static> SimplePreparedQuery<S> {
}
}
QueryVariants::Describe {
algebra, base_iri, ..
algebra,
base_iri,
dataset,
} => {
let dataset = Rc::new(DatasetView::new(
store,
options.default_graph_as_union,
&dataset,
)?);
let (plan, _) = PlanBuilder::build(dataset.as_ref(), &algebra)?;
SimplePreparedQueryAction::Describe {
plan: Rc::new(plan),
@ -221,7 +246,7 @@ impl QueryOptions {
pub trait ServiceHandler {
type Error: Error + Send + Sync + 'static;
/// Evaluates a `Query` against a given service identified by a `NamedNode`.
/// Evaluates a [`Query`](struct.Query.html) against a given service identified by a [`NamedNode`](../model/struct.NamedNode.html).
fn handle(&self, service_name: NamedNode, query: Query) -> Result<QueryResult, Self::Error>;
}

@ -35,7 +35,7 @@ fn sparql10_w3c_query_syntax_testsuite() -> Result<()> {
#[test]
fn sparql10_w3c_query_evaluation_testsuite() -> Result<()> {
run_testsuite("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/manifest-evaluation.ttl", vec![
// FROM and FROM name support that is missing
// FROM and FROM name tests support is not implemented yet
"http://www.w3.org/2001/sw/DataAccess/tests/data-r2/dataset/manifest#dawg-dataset-01",
"http://www.w3.org/2001/sw/DataAccess/tests/data-r2/dataset/manifest#dawg-dataset-03",
"http://www.w3.org/2001/sw/DataAccess/tests/data-r2/dataset/manifest#dawg-dataset-05",
@ -98,7 +98,7 @@ fn sparql11_query_w3c_evaluation_testsuite() -> Result<()> {
// SPARQL 1.1 JSON query results deserialization is not implemented yet
"http://www.w3.org/2009/sparql/docs/tests/data-sparql11/aggregates/manifest#agg-empty-group-count-1",
"http://www.w3.org/2009/sparql/docs/tests/data-sparql11/aggregates/manifest#agg-empty-group-count-2",
// FROM support
// FROM tests support
"http://www.w3.org/2009/sparql/docs/tests/data-sparql11/construct/manifest#constructwhere04",
//BNODE() scope is currently wrong
"http://www.w3.org/2009/sparql/docs/tests/data-sparql11/functions/manifest#bnode01",

Loading…
Cancel
Save