Drops base_iri from QueryOptions and allows to Give a Query object to execute

The base IRI should now be given to the Query::parse method
pull/46/head
Tpt 4 years ago
parent 90d4baae2a
commit 36bc870ca8
  1. 35
      lib/src/sparql/mod.rs
  2. 17
      lib/src/sparql/parser.rs
  3. 10
      lib/src/store/memory.rs
  4. 18
      lib/src/store/rocksdb.rs
  5. 18
      lib/src/store/sled.rs
  6. 30
      lib/tests/service_test_cases.rs
  7. 6
      testsuite/src/sparql_evaluator.rs

@ -18,7 +18,6 @@ use crate::sparql::plan_builder::PlanBuilder;
use crate::store::ReadableEncodedStore;
use crate::Error;
use crate::Result;
use oxiri::Iri;
pub use crate::sparql::algebra::GraphPattern;
pub use crate::sparql::model::QuerySolution;
@ -30,6 +29,7 @@ pub use crate::sparql::model::QueryResultSyntax;
pub use crate::sparql::model::Variable;
pub use crate::sparql::parser::Query;
pub use crate::sparql::parser::SparqlParseError;
use std::convert::TryInto;
/// A prepared [SPARQL query](https://www.w3.org/TR/sparql11-query/)
#[deprecated(
@ -62,9 +62,13 @@ enum SimplePreparedQueryAction<S: ReadableEncodedStore> {
}
impl<S: ReadableEncodedStore> SimplePreparedQuery<S> {
pub(crate) fn new(store: S, query: &str, options: QueryOptions<'_>) -> Result<Self> {
pub(crate) fn new(
store: S,
query: impl TryInto<Query, Error = impl Into<Error>>,
options: QueryOptions,
) -> Result<Self> {
let dataset = DatasetView::new(store, options.default_graph_as_union);
Ok(Self(match Query::parse(query, options.base_iri)?.0 {
Ok(Self(match query.try_into().map_err(|e| e.into())?.0 {
QueryVariants::Select {
algebra, base_iri, ..
} => {
@ -117,19 +121,14 @@ impl<S: ReadableEncodedStore> SimplePreparedQuery<S> {
pub(crate) fn new_from_pattern(
store: S,
pattern: &GraphPattern,
options: QueryOptions<'_>,
options: QueryOptions,
) -> Result<Self> {
let dataset = DatasetView::new(store, options.default_graph_as_union);
let (plan, variables) = PlanBuilder::build(dataset.encoder(), pattern)?;
let base_iri = if let Some(base_iri) = options.base_iri {
Some(Iri::parse(base_iri.to_string())?)
} else {
None
};
Ok(Self(SimplePreparedQueryAction::Select {
plan,
variables,
evaluator: SimpleEvaluator::new(dataset, base_iri, options.service_handler),
evaluator: SimpleEvaluator::new(dataset, None, options.service_handler),
}))
}
@ -190,30 +189,22 @@ impl ServiceHandler for EmptyServiceHandler {
}
}
/// Options for SPARQL query parsing and evaluation like the query base IRI
pub struct QueryOptions<'a> {
pub(crate) base_iri: Option<&'a str>,
/// Options for SPARQL query evaluation
pub struct QueryOptions {
pub(crate) default_graph_as_union: bool,
pub(crate) service_handler: Box<dyn ServiceHandler>,
}
impl<'a> Default for QueryOptions<'a> {
impl Default for QueryOptions {
fn default() -> Self {
Self {
base_iri: None,
default_graph_as_union: false,
service_handler: Box::new(EmptyServiceHandler),
}
}
}
impl<'a> QueryOptions<'a> {
/// Allows setting 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
}
impl QueryOptions {
/// Consider the union of all graphs in the store as the default graph
pub const fn with_default_graph_as_union(mut self) -> Self {
self.default_graph_as_union = true;

@ -9,6 +9,7 @@ use peg::parser;
use peg::str::LineCol;
use std::borrow::Cow;
use std::collections::{HashMap, HashSet};
use std::convert::TryFrom;
use std::error::Error;
use std::str::Chars;
use std::str::FromStr;
@ -61,6 +62,22 @@ impl FromStr for Query {
}
}
impl<'a> TryFrom<&'a str> for Query {
type Error = SparqlParseError;
fn try_from(query: &str) -> Result<Self, SparqlParseError> {
Self::from_str(query)
}
}
impl<'a> TryFrom<&'a String> for Query {
type Error = SparqlParseError;
fn try_from(query: &String) -> Result<Self, SparqlParseError> {
Self::from_str(query)
}
}
/// Error returned during SPARQL parsing.
#[derive(Debug)]
pub struct SparqlParseError {

@ -2,13 +2,13 @@
use crate::error::UnwrapInfallible;
use crate::model::*;
use crate::sparql::{GraphPattern, QueryOptions, QueryResult, SimplePreparedQuery};
use crate::sparql::{GraphPattern, Query, QueryOptions, QueryResult, SimplePreparedQuery};
use crate::store::numeric_encoder::*;
use crate::store::{load_dataset, load_graph, ReadableEncodedStore, WritableEncodedStore};
use crate::{DatasetSyntax, Error, GraphSyntax};
use std::collections::hash_map::DefaultHasher;
use std::collections::{HashMap, HashSet};
use std::convert::Infallible;
use std::convert::{Infallible, TryInto};
use std::fmt;
use std::hash::{BuildHasherDefault, Hash, Hasher};
use std::io::BufRead;
@ -105,8 +105,8 @@ impl MemoryStore {
/// ```
pub fn prepare_query(
&self,
query: &str,
options: QueryOptions<'_>,
query: impl TryInto<Query, Error = impl Into<Error>>,
options: QueryOptions,
) -> crate::Result<MemoryPreparedQuery> {
Ok(MemoryPreparedQuery(SimplePreparedQuery::new(
self.clone(),
@ -119,7 +119,7 @@ impl MemoryStore {
pub fn prepare_query_from_pattern(
&self,
graph_pattern: &GraphPattern,
options: QueryOptions<'_>,
options: QueryOptions,
) -> crate::Result<MemoryPreparedQuery> {
Ok(MemoryPreparedQuery(SimplePreparedQuery::new_from_pattern(
self.clone(),

@ -2,12 +2,12 @@
use crate::error::UnwrapInfallible;
use crate::model::*;
use crate::sparql::{GraphPattern, QueryOptions, QueryResult, SimplePreparedQuery};
use crate::sparql::{GraphPattern, Query, QueryOptions, QueryResult, SimplePreparedQuery};
use crate::store::numeric_encoder::*;
use crate::store::{load_dataset, load_graph, ReadableEncodedStore, WritableEncodedStore};
use crate::{DatasetSyntax, GraphSyntax, Result};
use rocksdb::*;
use std::convert::Infallible;
use std::convert::{Infallible, TryInto};
use std::io::{BufRead, Cursor};
use std::mem::{take, transmute};
use std::path::Path;
@ -92,10 +92,10 @@ impl RocksDbStore {
/// Prepares a [SPARQL 1.1 query](https://www.w3.org/TR/sparql11-query/) and returns an object that could be used to execute it.
///
/// See `MemoryStore` for a usage example.
pub fn prepare_query<'a>(
&'a self,
query: &str,
options: QueryOptions<'_>,
pub fn prepare_query(
&self,
query: impl TryInto<Query, Error = impl Into<crate::Error>>,
options: QueryOptions,
) -> Result<RocksDbPreparedQuery> {
Ok(RocksDbPreparedQuery(SimplePreparedQuery::new(
(*self).clone(),
@ -105,10 +105,10 @@ impl RocksDbStore {
}
/// This is similar to `prepare_query`, but useful if a SPARQL query has already been parsed, which is the case when building `ServiceHandler`s for federated queries with `SERVICE` clauses. For examples, look in the tests.
pub fn prepare_query_from_pattern<'a>(
&'a self,
pub fn prepare_query_from_pattern(
&self,
graph_pattern: &GraphPattern,
options: QueryOptions<'_>,
options: QueryOptions,
) -> Result<RocksDbPreparedQuery> {
Ok(RocksDbPreparedQuery(SimplePreparedQuery::new_from_pattern(
(*self).clone(),

@ -2,12 +2,12 @@
use crate::error::UnwrapInfallible;
use crate::model::*;
use crate::sparql::{GraphPattern, QueryOptions, QueryResult, SimplePreparedQuery};
use crate::sparql::{GraphPattern, Query, QueryOptions, QueryResult, SimplePreparedQuery};
use crate::store::numeric_encoder::*;
use crate::store::{load_dataset, load_graph, ReadableEncodedStore, WritableEncodedStore};
use crate::{DatasetSyntax, Error, GraphSyntax, Result};
use sled::{Batch, Config, Iter, Tree};
use std::convert::Infallible;
use std::convert::{Infallible, TryInto};
use std::io::{BufRead, Cursor};
use std::path::Path;
use std::{fmt, str};
@ -87,10 +87,10 @@ impl SledStore {
/// Prepares a [SPARQL 1.1 query](https://www.w3.org/TR/sparql11-query/) and returns an object that could be used to execute it.
///
/// See `MemoryStore` for a usage example.
pub fn prepare_query<'a>(
&'a self,
query: &str,
options: QueryOptions<'_>,
pub fn prepare_query(
&self,
query: impl TryInto<Query, Error = impl Into<Error>>,
options: QueryOptions,
) -> Result<SledPreparedQuery> {
Ok(SledPreparedQuery(SimplePreparedQuery::new(
(*self).clone(),
@ -100,10 +100,10 @@ impl SledStore {
}
/// This is similar to `prepare_query`, but useful if a SPARQL query has already been parsed, which is the case when building `ServiceHandler`s for federated queries with `SERVICE` clauses. For examples, look in the tests.
pub fn prepare_query_from_pattern<'a>(
&'a self,
pub fn prepare_query_from_pattern(
&self,
graph_pattern: &GraphPattern,
options: QueryOptions<'_>,
options: QueryOptions,
) -> Result<SledPreparedQuery> {
Ok(SledPreparedQuery(SimplePreparedQuery::new_from_pattern(
(*self).clone(),

@ -30,7 +30,7 @@ fn simple_service_test() {
.to_string();
let options = QueryOptions::default().with_service_handler(TestServiceHandler);
let collected = do_query(b"".as_ref(), query, options)
let collected = do_query(b"".as_ref(), &query, options)
.unwrap()
.map(|b| {
b.unwrap()
@ -93,7 +93,7 @@ fn two_service_test() {
.to_string();
let options = QueryOptions::default().with_service_handler(TwoServiceTest);
let collected = do_query(b"".as_ref(), query, options)
let collected = do_query(b"".as_ref(), &query, options)
.unwrap()
.map(|b| {
b.unwrap()
@ -139,7 +139,7 @@ fn silent_service_empty_set_test() {
let triples = b"".as_ref();
let options = QueryOptions::default().with_service_handler(ServiceTest);
assert_eq!(do_query(triples, query, options).unwrap().count(), 1);
assert_eq!(do_query(triples, &query, options).unwrap().count(), 1);
}
#[test]
@ -172,7 +172,7 @@ fn non_silent_service_test() {
let triples = b"".as_ref();
let options = QueryOptions::default().with_service_handler(ServiceTest);
let mut solutions = do_query(triples, query, options).unwrap();
let mut solutions = do_query(triples, &query, options).unwrap();
if let Some(Err(_)) = solutions.next() {
} else {
panic!("This should have been an error since the service fails")
@ -204,12 +204,12 @@ fn make_store(reader: impl BufRead) -> Result<MemoryStore> {
Ok(store)
}
fn query_store<'a>(
fn query_store(
store: MemoryStore,
query: String,
options: QueryOptions<'a>,
) -> Result<QuerySolutionsIterator<'a>> {
match store.prepare_query(&query, options)?.exec()? {
query: &str,
options: QueryOptions,
) -> Result<QuerySolutionsIterator<'_>> {
match store.prepare_query(query, options)?.exec()? {
QueryResult::Solutions(iterator) => {
let (variables, iter) = iterator.destruct();
let collected = iter.collect::<Vec<_>>();
@ -225,7 +225,7 @@ fn query_store<'a>(
fn pattern_store<'a>(
store: MemoryStore,
pattern: &'a GraphPattern,
options: QueryOptions<'a>,
options: QueryOptions,
) -> Result<QuerySolutionsIterator<'a>> {
match store
.prepare_query_from_pattern(&pattern, options)?
@ -243,11 +243,11 @@ fn pattern_store<'a>(
}
}
fn do_query<'a>(
fn do_query(
reader: impl BufRead,
query: String,
options: QueryOptions<'a>,
) -> Result<QuerySolutionsIterator<'a>> {
query: &str,
options: QueryOptions,
) -> Result<QuerySolutionsIterator<'_>> {
let store = make_store(reader)?;
query_store(store, query, options)
}
@ -255,7 +255,7 @@ fn do_query<'a>(
fn do_pattern<'a>(
reader: impl BufRead,
pattern: &'a GraphPattern,
options: QueryOptions<'a>,
options: QueryOptions,
) -> Result<QuerySolutionsIterator<'a>> {
let store = make_store(reader)?;
pattern_store(store, pattern, options)

@ -83,9 +83,11 @@ fn evaluate_sparql_test(test: &Test) -> Result<()> {
.as_deref()
.ok_or_else(|| Error::msg(format!("No action found for test {}", test)))?;
let options = QueryOptions::default()
.with_base_iri(query_file)
.with_service_handler(StaticServiceHandler::new(&test.service_data)?);
match store.prepare_query(&read_file_to_string(query_file)?, options) {
match store.prepare_query(
Query::parse(&read_file_to_string(query_file)?, Some(query_file))?,
options,
) {
Err(error) => Err(Error::msg(format!(
"Failure to parse query of {} with error: {}",
test, error

Loading…
Cancel
Save