From 45d78d490de21297fa5cd9b51f923cc2df7a7afe Mon Sep 17 00:00:00 2001 From: Tpt Date: Fri, 23 Aug 2019 20:03:21 +0200 Subject: [PATCH] Makes RepositoryConnection.prepare_query take &str instead of Read Simpler and faster API (SPARQL parser was reading into a String anyway) --- lib/src/lib.rs | 2 +- lib/src/repository.rs | 8 ++++---- lib/src/sparql/mod.rs | 7 +++---- lib/src/sparql/parser.rs | 16 ++++------------ lib/src/store/memory.rs | 2 +- lib/src/store/mod.rs | 4 ++-- lib/src/store/rocksdb.rs | 2 +- lib/tests/sparql_test_cases.rs | 13 +++++-------- server/src/main.rs | 8 +++++--- 9 files changed, 26 insertions(+), 36 deletions(-) diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 659b25ba..4947f317 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -27,7 +27,7 @@ //! assert_eq!(vec![quad], results.unwrap()); //! //! // 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(); //! if let QueryResult::Bindings(results) = results { //! assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into())); diff --git a/lib/src/repository.rs b/lib/src/repository.rs index 19c36c91..68219d00 100644 --- a/lib/src/repository.rs +++ b/lib/src/repository.rs @@ -1,7 +1,7 @@ use crate::model::*; use crate::sparql::PreparedQuery; 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) /// and allows to query and update it using SPARQL. @@ -30,7 +30,7 @@ use std::io::{BufRead, Read}; /// assert_eq!(vec![quad], results.unwrap()); /// /// // 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(); /// if let QueryResult::Bindings(results) = results { /// 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)); /// /// // 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(); /// if let QueryResult::Bindings(results) = results { /// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into())); /// } /// ``` - fn prepare_query(&self, query: impl Read) -> Result; + fn prepare_query(&self, query: &str) -> Result; /// Retrieves quads with a filter on each quad component /// diff --git a/lib/src/sparql/mod.rs b/lib/src/sparql/mod.rs index eca66aa1..fc0ffbbe 100644 --- a/lib/src/sparql/mod.rs +++ b/lib/src/sparql/mod.rs @@ -17,7 +17,6 @@ use crate::sparql::plan_builder::PlanBuilder; use crate::store::StoreConnection; use crate::Result; use std::fmt; -use std::io::Read; pub use crate::sparql::model::BindingsIterator; pub use crate::sparql::model::QueryResult; @@ -55,7 +54,7 @@ enum SimplePreparedQueryOptions { } impl SimplePreparedQuery { - pub(crate) fn new(connection: S, query: impl Read) -> Result { + pub(crate) fn new(connection: S, query: &str) -> Result { Ok(Self(match read_sparql_query(query, None)? { QueryVariants::Select { algebra, @@ -143,7 +142,7 @@ impl fmt::Display for Query { impl Query { /// Parses a SPARQL query - pub fn read<'a>(reader: impl Read + 'a, base_iri: Option<&'a str>) -> Result { - Ok(Query(read_sparql_query(reader, base_iri)?)) + pub fn parse(query: &str, base_iri: Option<&str>) -> Result { + Ok(Query(read_sparql_query(query, base_iri)?)) } } diff --git a/lib/src/sparql/parser.rs b/lib/src/sparql/parser.rs index 2bf60200..7fd43164 100644 --- a/lib/src/sparql/parser.rs +++ b/lib/src/sparql/parser.rs @@ -19,8 +19,6 @@ mod grammar { use std::char; use std::collections::BTreeMap; use std::collections::HashMap; - use std::io::BufReader; - use std::io::Read; use std::str::Chars; struct FocusedTriplePattern { @@ -533,9 +531,9 @@ mod grammar { include!(concat!(env!("OUT_DIR"), "/sparql_grammar.rs")); - pub fn read_sparql_query<'a, R: Read + 'a>( - source: R, - base_iri: Option<&'a str>, + pub fn read_sparql_query( + query: &str, + base_iri: Option<&str>, ) -> super::super::super::Result { let mut state = ParserState { base_iri: if let Some(base_iri) = base_iri { @@ -548,13 +546,7 @@ mod grammar { aggregations: BTreeMap::default(), }; - let mut string_buffer = String::default(); - BufReader::new(source).read_to_string(&mut string_buffer)?; - - Ok(QueryUnit( - &unescape_unicode_codepoints(&string_buffer), - &mut state, - )?) + Ok(QueryUnit(&unescape_unicode_codepoints(query), &mut state)?) } } diff --git a/lib/src/store/memory.rs b/lib/src/store/memory.rs index 3ec9f60e..65421ecb 100644 --- a/lib/src/store/memory.rs +++ b/lib/src/store/memory.rs @@ -32,7 +32,7 @@ use std::sync::RwLockWriteGuard; /// assert_eq!(vec![quad], results.unwrap()); /// /// // 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(); /// if let QueryResult::Bindings(results) = results { /// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into())); diff --git a/lib/src/store/mod.rs b/lib/src/store/mod.rs index b6ffd04e..e964c703 100644 --- a/lib/src/store/mod.rs +++ b/lib/src/store/mod.rs @@ -17,7 +17,7 @@ use rio_api::parser::{QuadParser, TripleParser}; use rio_turtle::{NQuadsParser, NTriplesParser, TriGParser, TurtleParser}; use rio_xml::RdfXmlParser; use std::collections::HashMap; -use std::io::{BufRead, Read}; +use std::io::BufRead; use std::iter::{once, Iterator}; /// Defines the `Store` traits that is used to have efficient binary storage @@ -59,7 +59,7 @@ impl From for StoreRepositoryConnection { impl RepositoryConnection for StoreRepositoryConnection { type PreparedQuery = SimplePreparedQuery; - fn prepare_query(&self, query: impl Read) -> Result> { + fn prepare_query(&self, query: &str) -> Result> { SimplePreparedQuery::new(self.inner.clone(), query) //TODO: avoid clone } diff --git a/lib/src/store/rocksdb.rs b/lib/src/store/rocksdb.rs index 601ec2b9..4fe8fb78 100644 --- a/lib/src/store/rocksdb.rs +++ b/lib/src/store/rocksdb.rs @@ -42,7 +42,7 @@ use std::sync::Mutex; /// assert_eq!(vec![quad], results.unwrap()); /// /// // 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(); /// if let QueryResult::Bindings(results) = results { /// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into())); diff --git a/lib/tests/sparql_test_cases.rs b/lib/tests/sparql_test_cases.rs index b3db0554..62c0a3c5 100644 --- a/lib/tests/sparql_test_cases.rs +++ b/lib/tests/sparql_test_cases.rs @@ -31,10 +31,10 @@ fn sparql_w3c_syntax_testsuite() -> Result<()> { continue; } 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), 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!( false, "Failure to deserialize \"{}\" of {} with error: {}", @@ -47,7 +47,8 @@ fn sparql_w3c_syntax_testsuite() -> Result<()> { } } else if test.kind == "NegativeSyntaxTest" || test.kind == "NegativeSyntaxTest11" { //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); } } else { @@ -128,7 +129,7 @@ fn sparql_w3c_query_evaluation_testsuite() -> Result<()> { } match repository .connection()? - .prepare_query(read_file(&test.query)?) + .prepare_query(&read_file_to_string(&test.query)?) { Err(error) => assert!( false, @@ -214,10 +215,6 @@ fn load_sparql_query_result_graph(url: &str) -> Result { } } -fn load_query(url: &str) -> Result { - Query::read(read_file(&url)?, Some(&url)) -} - fn to_relative_path(url: &str) -> Result { if url.starts_with("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/") { Ok(url.replace( diff --git a/server/src/main.rs b/server/src/main.rs index 5a30d057..e1b8c7c1 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -96,7 +96,9 @@ fn handle_request( if let Some(mut body) = request.data() { if let Some(content_type) = request.header("Content-Type") { 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") { let mut buffer = Vec::default(); body.read_to_end(&mut buffer).unwrap(); @@ -124,13 +126,13 @@ fn evaluate_urlencoded_sparql_query( encoded: &[u8], ) -> Response { 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 { Response::text("You should set the 'query' parameter").with_status_code(400) } } -fn evaluate_sparql_query(connection: R, query: impl Read) -> Response { +fn evaluate_sparql_query(connection: R, query: &str) -> Response { //TODO: stream match connection.prepare_query(query) { Ok(query) => match query.exec().unwrap() {