Makes RepositoryConnection.prepare_query take &str instead of Read

Simpler and faster API (SPARQL parser was reading into a String anyway)
pull/10/head
Tpt 5 years ago
parent 9339e1063e
commit 45d78d490d
  1. 2
      lib/src/lib.rs
  2. 8
      lib/src/repository.rs
  3. 7
      lib/src/sparql/mod.rs
  4. 16
      lib/src/sparql/parser.rs
  5. 2
      lib/src/store/memory.rs
  6. 4
      lib/src/store/mod.rs
  7. 2
      lib/src/store/rocksdb.rs
  8. 13
      lib/tests/sparql_test_cases.rs
  9. 8
      server/src/main.rs

@ -27,7 +27,7 @@
//! assert_eq!(vec![quad], results.unwrap()); //! assert_eq!(vec![quad], results.unwrap());
//! //!
//! // SPARQL query //! // SPARQL query
//! let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }".as_bytes()).unwrap(); //! let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }").unwrap();
//! let results = prepared_query.exec().unwrap(); //! let results = prepared_query.exec().unwrap();
//! if let QueryResult::Bindings(results) = results { //! if let QueryResult::Bindings(results) = results {
//! assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into())); //! assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into()));

@ -1,7 +1,7 @@
use crate::model::*; use crate::model::*;
use crate::sparql::PreparedQuery; use crate::sparql::PreparedQuery;
use crate::{DatasetSyntax, GraphSyntax, Result}; use crate::{DatasetSyntax, GraphSyntax, Result};
use std::io::{BufRead, Read}; use std::io::BufRead;
/// A `Repository` stores a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) /// A `Repository` stores a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset)
/// and allows to query and update it using SPARQL. /// and allows to query and update it using SPARQL.
@ -30,7 +30,7 @@ use std::io::{BufRead, Read};
/// assert_eq!(vec![quad], results.unwrap()); /// assert_eq!(vec![quad], results.unwrap());
/// ///
/// // SPARQL query /// // SPARQL query
/// let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }".as_bytes()).unwrap(); /// let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }").unwrap();
/// let results = prepared_query.exec().unwrap(); /// let results = prepared_query.exec().unwrap();
/// if let QueryResult::Bindings(results) = results { /// if let QueryResult::Bindings(results) = results {
/// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into())); /// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into()));
@ -75,13 +75,13 @@ pub trait RepositoryConnection: Clone {
/// connection.insert(&Quad::new(ex.clone(), ex.clone(), ex.clone(), None)); /// connection.insert(&Quad::new(ex.clone(), ex.clone(), ex.clone(), None));
/// ///
/// // SPARQL query /// // SPARQL query
/// let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }".as_bytes()).unwrap(); /// let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }").unwrap();
/// let results = prepared_query.exec().unwrap(); /// let results = prepared_query.exec().unwrap();
/// if let QueryResult::Bindings(results) = results { /// if let QueryResult::Bindings(results) = results {
/// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into())); /// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into()));
/// } /// }
/// ``` /// ```
fn prepare_query(&self, query: impl Read) -> Result<Self::PreparedQuery>; fn prepare_query(&self, query: &str) -> Result<Self::PreparedQuery>;
/// Retrieves quads with a filter on each quad component /// Retrieves quads with a filter on each quad component
/// ///

@ -17,7 +17,6 @@ use crate::sparql::plan_builder::PlanBuilder;
use crate::store::StoreConnection; use crate::store::StoreConnection;
use crate::Result; use crate::Result;
use std::fmt; use std::fmt;
use std::io::Read;
pub use crate::sparql::model::BindingsIterator; pub use crate::sparql::model::BindingsIterator;
pub use crate::sparql::model::QueryResult; pub use crate::sparql::model::QueryResult;
@ -55,7 +54,7 @@ enum SimplePreparedQueryOptions<S: StoreConnection> {
} }
impl<S: StoreConnection> SimplePreparedQuery<S> { impl<S: StoreConnection> SimplePreparedQuery<S> {
pub(crate) fn new(connection: S, query: impl Read) -> Result<Self> { pub(crate) fn new(connection: S, query: &str) -> Result<Self> {
Ok(Self(match read_sparql_query(query, None)? { Ok(Self(match read_sparql_query(query, None)? {
QueryVariants::Select { QueryVariants::Select {
algebra, algebra,
@ -143,7 +142,7 @@ impl fmt::Display for Query {
impl Query { impl Query {
/// Parses a SPARQL query /// Parses a SPARQL query
pub fn read<'a>(reader: impl Read + 'a, base_iri: Option<&'a str>) -> Result<Self> { pub fn parse(query: &str, base_iri: Option<&str>) -> Result<Self> {
Ok(Query(read_sparql_query(reader, base_iri)?)) Ok(Query(read_sparql_query(query, base_iri)?))
} }
} }

@ -19,8 +19,6 @@ mod grammar {
use std::char; use std::char;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::collections::HashMap; use std::collections::HashMap;
use std::io::BufReader;
use std::io::Read;
use std::str::Chars; use std::str::Chars;
struct FocusedTriplePattern<F> { struct FocusedTriplePattern<F> {
@ -533,9 +531,9 @@ mod grammar {
include!(concat!(env!("OUT_DIR"), "/sparql_grammar.rs")); include!(concat!(env!("OUT_DIR"), "/sparql_grammar.rs"));
pub fn read_sparql_query<'a, R: Read + 'a>( pub fn read_sparql_query(
source: R, query: &str,
base_iri: Option<&'a str>, base_iri: Option<&str>,
) -> super::super::super::Result<QueryVariants> { ) -> super::super::super::Result<QueryVariants> {
let mut state = ParserState { let mut state = ParserState {
base_iri: if let Some(base_iri) = base_iri { base_iri: if let Some(base_iri) = base_iri {
@ -548,13 +546,7 @@ mod grammar {
aggregations: BTreeMap::default(), aggregations: BTreeMap::default(),
}; };
let mut string_buffer = String::default(); Ok(QueryUnit(&unescape_unicode_codepoints(query), &mut state)?)
BufReader::new(source).read_to_string(&mut string_buffer)?;
Ok(QueryUnit(
&unescape_unicode_codepoints(&string_buffer),
&mut state,
)?)
} }
} }

@ -32,7 +32,7 @@ use std::sync::RwLockWriteGuard;
/// assert_eq!(vec![quad], results.unwrap()); /// assert_eq!(vec![quad], results.unwrap());
/// ///
/// // SPARQL query /// // SPARQL query
/// let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }".as_bytes()).unwrap(); /// let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }").unwrap();
/// let results = prepared_query.exec().unwrap(); /// let results = prepared_query.exec().unwrap();
/// if let QueryResult::Bindings(results) = results { /// if let QueryResult::Bindings(results) = results {
/// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into())); /// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into()));

@ -17,7 +17,7 @@ use rio_api::parser::{QuadParser, TripleParser};
use rio_turtle::{NQuadsParser, NTriplesParser, TriGParser, TurtleParser}; use rio_turtle::{NQuadsParser, NTriplesParser, TriGParser, TurtleParser};
use rio_xml::RdfXmlParser; use rio_xml::RdfXmlParser;
use std::collections::HashMap; use std::collections::HashMap;
use std::io::{BufRead, Read}; use std::io::BufRead;
use std::iter::{once, Iterator}; use std::iter::{once, Iterator};
/// Defines the `Store` traits that is used to have efficient binary storage /// Defines the `Store` traits that is used to have efficient binary storage
@ -59,7 +59,7 @@ impl<S: StoreConnection> From<S> for StoreRepositoryConnection<S> {
impl<S: StoreConnection> RepositoryConnection for StoreRepositoryConnection<S> { impl<S: StoreConnection> RepositoryConnection for StoreRepositoryConnection<S> {
type PreparedQuery = SimplePreparedQuery<S>; type PreparedQuery = SimplePreparedQuery<S>;
fn prepare_query(&self, query: impl Read) -> Result<SimplePreparedQuery<S>> { fn prepare_query(&self, query: &str) -> Result<SimplePreparedQuery<S>> {
SimplePreparedQuery::new(self.inner.clone(), query) //TODO: avoid clone SimplePreparedQuery::new(self.inner.clone(), query) //TODO: avoid clone
} }

@ -42,7 +42,7 @@ use std::sync::Mutex;
/// assert_eq!(vec![quad], results.unwrap()); /// assert_eq!(vec![quad], results.unwrap());
/// ///
/// // SPARQL query /// // SPARQL query
/// let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }".as_bytes()).unwrap(); /// let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }").unwrap();
/// let results = prepared_query.exec().unwrap(); /// let results = prepared_query.exec().unwrap();
/// if let QueryResult::Bindings(results) = results { /// if let QueryResult::Bindings(results) = results {
/// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into())); /// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into()));

@ -31,10 +31,10 @@ fn sparql_w3c_syntax_testsuite() -> Result<()> {
continue; continue;
} }
if test.kind == "PositiveSyntaxTest" || test.kind == "PositiveSyntaxTest11" { if test.kind == "PositiveSyntaxTest" || test.kind == "PositiveSyntaxTest11" {
match load_query(&test.query) { match Query::parse(&read_file_to_string(&test.query)?, Some(&test.query)) {
Err(error) => assert!(false, "Failure on {} with error: {}", test, error), Err(error) => assert!(false, "Failure on {} with error: {}", test, error),
Ok(query) => { Ok(query) => {
if let Err(error) = Query::read(query.to_string().as_bytes(), None) { if let Err(error) = Query::parse(&query.to_string(), None) {
assert!( assert!(
false, false,
"Failure to deserialize \"{}\" of {} with error: {}", "Failure to deserialize \"{}\" of {} with error: {}",
@ -47,7 +47,8 @@ fn sparql_w3c_syntax_testsuite() -> Result<()> {
} }
} else if test.kind == "NegativeSyntaxTest" || test.kind == "NegativeSyntaxTest11" { } else if test.kind == "NegativeSyntaxTest" || test.kind == "NegativeSyntaxTest11" {
//TODO //TODO
if let Ok(result) = load_query(&test.query) { if let Ok(result) = Query::parse(&read_file_to_string(&test.query)?, Some(&test.query))
{
eprintln!("Failure on {}. The output tree is: {}", test, result); eprintln!("Failure on {}. The output tree is: {}", test, result);
} }
} else { } else {
@ -128,7 +129,7 @@ fn sparql_w3c_query_evaluation_testsuite() -> Result<()> {
} }
match repository match repository
.connection()? .connection()?
.prepare_query(read_file(&test.query)?) .prepare_query(&read_file_to_string(&test.query)?)
{ {
Err(error) => assert!( Err(error) => assert!(
false, false,
@ -214,10 +215,6 @@ fn load_sparql_query_result_graph(url: &str) -> Result<SimpleGraph> {
} }
} }
fn load_query(url: &str) -> Result<Query> {
Query::read(read_file(&url)?, Some(&url))
}
fn to_relative_path(url: &str) -> Result<String> { fn to_relative_path(url: &str) -> Result<String> {
if url.starts_with("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/") { if url.starts_with("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/") {
Ok(url.replace( Ok(url.replace(

@ -96,7 +96,9 @@ fn handle_request<R: RepositoryConnection>(
if let Some(mut body) = request.data() { if let Some(mut body) = request.data() {
if let Some(content_type) = request.header("Content-Type") { if let Some(content_type) = request.header("Content-Type") {
if content_type.starts_with("application/sparql-query") { if content_type.starts_with("application/sparql-query") {
evaluate_sparql_query(connection, body) let mut buffer = String::default();
body.read_to_string(&mut buffer).unwrap();
evaluate_sparql_query(connection, &buffer)
} else if content_type.starts_with("application/x-www-form-urlencoded") { } else if content_type.starts_with("application/x-www-form-urlencoded") {
let mut buffer = Vec::default(); let mut buffer = Vec::default();
body.read_to_end(&mut buffer).unwrap(); body.read_to_end(&mut buffer).unwrap();
@ -124,13 +126,13 @@ fn evaluate_urlencoded_sparql_query<R: RepositoryConnection>(
encoded: &[u8], encoded: &[u8],
) -> Response { ) -> Response {
if let Some((_, query)) = form_urlencoded::parse(encoded).find(|(k, _)| k == "query") { if let Some((_, query)) = form_urlencoded::parse(encoded).find(|(k, _)| k == "query") {
evaluate_sparql_query(connection, query.as_bytes()) evaluate_sparql_query(connection, &query)
} else { } else {
Response::text("You should set the 'query' parameter").with_status_code(400) Response::text("You should set the 'query' parameter").with_status_code(400)
} }
} }
fn evaluate_sparql_query<R: RepositoryConnection>(connection: R, query: impl Read) -> Response { fn evaluate_sparql_query<R: RepositoryConnection>(connection: R, query: &str) -> Response {
//TODO: stream //TODO: stream
match connection.prepare_query(query) { match connection.prepare_query(query) {
Ok(query) => match query.exec().unwrap() { Ok(query) => match query.exec().unwrap() {

Loading…
Cancel
Save