Drops dependency on anyhow to get something implementing std::error::Error

Closes #25
pull/26/head
Tpt 5 years ago
parent 73f61884c1
commit 23f5ac78ed
  1. 2
      lib/Cargo.toml
  2. 36
      lib/benches/sparql_query.rs
  3. 130
      lib/src/error.rs
  4. 3
      lib/src/lib.rs
  5. 37
      lib/src/model/error.rs
  6. 2
      lib/src/model/mod.rs
  7. 5
      lib/src/model/named_node.rs
  8. 8
      lib/src/sparql/eval.rs
  9. 6
      lib/src/sparql/json_results.rs
  10. 4
      lib/src/sparql/mod.rs
  11. 8
      lib/src/sparql/model.rs
  12. 12
      lib/src/sparql/plan_builder.rs
  13. 70
      lib/src/sparql/xml_results.rs
  14. 25
      lib/src/store/memory.rs
  15. 6
      lib/src/store/mod.rs
  16. 24
      lib/src/store/numeric_encoder.rs
  17. 4
      lib/src/store/rocksdb.rs
  18. 17
      lib/tests/service_test_cases.rs
  19. 56
      lib/tests/sparql_test_cases.rs
  20. 2
      wikibase/Cargo.toml
  21. 23
      wikibase/src/loader.rs

@ -20,7 +20,6 @@ md-5 = "0.8"
sha-1 = "0.8"
sha2 = "0.8"
digest = "0.8"
anyhow = "1"
regex = "1"
rio_api = "0.4"
rio_turtle = "0.4"
@ -35,6 +34,7 @@ js-sys = "0.3"
[dev-dependencies]
rayon = "1"
criterion = "0.3"
anyhow = "1"
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
wasm-bindgen-test = "0.3"

@ -1,4 +1,3 @@
use anyhow::anyhow;
use criterion::{criterion_group, criterion_main, Criterion};
use oxigraph::model::vocab::rdf;
use oxigraph::model::*;
@ -55,7 +54,7 @@ fn to_relative_path(url: &str) -> Result<String> {
"rdf-tests/sparql11/",
))
} else {
Err(anyhow!("Not supported url for file: {}", url))
Err(Error::msg(format!("Not supported url for file: {}", url)))
}
}
@ -65,7 +64,11 @@ fn read_file(url: &str) -> Result<impl BufRead> {
base_path.push(to_relative_path(url)?);
Ok(BufReader::new(File::open(&base_path).map_err(|e| {
anyhow!("Opening file {} failed with {}", base_path.display(), e)
Error::msg(format!(
"Opening file {} failed with {}",
base_path.display(),
e,
))
})?))
}
@ -98,7 +101,10 @@ fn load_graph_to_repository(
} else if url.ends_with(".rdf") {
GraphSyntax::RdfXml
} else {
return Err(anyhow!("Serialization type not found for {}", url));
return Err(Error::msg(format!(
"Serialization type not found for {}",
url
)));
};
connection.load_graph(read_file(url)?, syntax, to_graph_name, Some(url))
}
@ -194,7 +200,7 @@ impl Iterator for TestManifest {
fn next(&mut self) -> Option<Result<Test>> {
match self.tests_to_do.pop() {
Some(Term::NamedNode(test_node)) => {
let test_subject = NamedOrBlankNode::from(test_node.clone());
let test_subject = NamedOrBlankNode::from(test_node);
let kind = match self
.graph
.object_for_subject_predicate(&test_subject, &rdf::TYPE)
@ -214,18 +220,21 @@ impl Iterator for TestManifest {
let n = n.clone().into();
match self.graph.object_for_subject_predicate(&n, &qt::QUERY) {
Some(Term::NamedNode(q)) => q.as_str().to_owned(),
Some(_) => return Some(Err(anyhow!("invalid query"))),
None => return Some(Err(anyhow!("query not found"))),
Some(_) => return Some(Err(Error::msg("invalid query"))),
None => return Some(Err(Error::msg("query not found"))),
}
}
Some(_) => return Some(Err(anyhow!("invalid action"))),
Some(_) => return Some(Err(Error::msg("invalid action"))),
None => {
return Some(Err(anyhow!("action not found for test {}", test_subject)));
return Some(Err(Error::msg(format!(
"action not found for test {}",
test_subject
))));
}
};
Some(Ok(Test { kind, query }))
}
Some(_) => Some(Err(anyhow!("invalid test list"))),
Some(_) => Some(Err(Error::msg("invalid test list"))),
None => {
match self.manifests_to_do.pop() {
Some(url) => {
@ -250,7 +259,7 @@ impl Iterator for TestManifest {
}),
);
}
Some(_) => return Some(Err(anyhow!("invalid tests list"))),
Some(_) => return Some(Err(Error::msg("invalid tests list"))),
None => (),
}
@ -266,7 +275,10 @@ impl Iterator for TestManifest {
));
}
Some(term) => {
return Some(Err(anyhow!("Invalid tests list. Got term {}", term)));
return Some(Err(Error::msg(format!(
"Invalid tests list. Got term {}",
term
))));
}
None => (),
}

@ -0,0 +1,130 @@
use crate::model::ModelError;
use peg::error::ParseError;
use peg::str::LineCol;
use rio_turtle::TurtleError;
use rio_xml::RdfXmlError;
use std::error;
use std::fmt;
use std::io;
use std::string::FromUtf8Error;
use std::sync::PoisonError;
#[derive(Debug)]
pub struct Error {
inner: ErrorKind,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.inner {
ErrorKind::Msg { msg } => write!(f, "{}", msg),
ErrorKind::Io(e) => e.fmt(f),
ErrorKind::FromUtf8(e) => e.fmt(f),
ErrorKind::Poison => write!(f, "Mutex was poisoned"),
ErrorKind::Model(e) => e.fmt(f),
ErrorKind::Other(e) => e.fmt(f),
}
}
}
impl error::Error for Error {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match &self.inner {
ErrorKind::Msg { .. } => None,
ErrorKind::Io(e) => Some(e),
ErrorKind::FromUtf8(e) => Some(e),
ErrorKind::Poison => None,
ErrorKind::Model(e) => Some(e),
ErrorKind::Other(e) => Some(e.as_ref()),
}
}
}
impl Error {
/// Wrap an other error
pub fn wrap(error: impl error::Error + Send + Sync + 'static) -> Self {
Self {
inner: ErrorKind::Other(Box::new(error)),
}
}
/// Builds an error from a printable error message.
pub fn msg(msg: impl Into<String>) -> Self {
Self {
inner: ErrorKind::Msg { msg: msg.into() },
}
}
}
#[derive(Debug)]
enum ErrorKind {
Msg { msg: String },
Io(io::Error),
FromUtf8(FromUtf8Error),
Poison,
Model(ModelError),
Other(Box<dyn error::Error + Send + Sync + 'static>),
}
impl From<io::Error> for Error {
fn from(error: io::Error) -> Self {
Self {
inner: ErrorKind::Io(error),
}
}
}
impl From<FromUtf8Error> for Error {
fn from(error: FromUtf8Error) -> Self {
Self {
inner: ErrorKind::FromUtf8(error),
}
}
}
impl<E: Into<ModelError>> From<E> for Error {
fn from(error: E) -> Self {
Self {
inner: ErrorKind::Model(error.into()),
}
}
}
impl From<TurtleError> for Error {
fn from(error: TurtleError) -> Self {
Self::wrap(error)
}
}
impl From<RdfXmlError> for Error {
fn from(error: RdfXmlError) -> Self {
Self::wrap(error)
}
}
impl From<quick_xml::Error> for Error {
fn from(error: quick_xml::Error) -> Self {
Self::wrap(error)
}
}
impl From<ParseError<LineCol>> for Error {
fn from(error: ParseError<LineCol>) -> Self {
Self::wrap(error)
}
}
impl<T> From<PoisonError<T>> for Error {
fn from(_: PoisonError<T>) -> Self {
Self {
inner: ErrorKind::Poison,
}
}
}
#[cfg(feature = "rocksdb")]
impl From<rocksdb::Error> for Error {
fn from(error: rocksdb::Error) -> Self {
Self::wrap(error)
}
}

@ -103,13 +103,14 @@
clippy::wrong_pub_self_convention,
)]
mod error;
pub mod model;
mod repository;
pub mod sparql;
pub(crate) mod store;
mod syntax;
pub use anyhow::Error;
pub use error::Error;
pub type Result<T> = ::std::result::Result<T, Error>;
pub use crate::repository::Repository;
pub use crate::repository::RepositoryConnection;

@ -0,0 +1,37 @@
use rio_api::iri::IriParseError;
use std::error;
use std::fmt;
#[derive(Debug)]
pub struct ModelError {
inner: ErrorKind,
}
impl fmt::Display for ModelError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.inner {
ErrorKind::Iri(e) => e.fmt(f),
}
}
}
impl error::Error for ModelError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match &self.inner {
ErrorKind::Iri(e) => Some(e),
}
}
}
#[derive(Debug)]
enum ErrorKind {
Iri(IriParseError),
}
impl From<IriParseError> for ModelError {
fn from(error: IriParseError) -> Self {
Self {
inner: ErrorKind::Iri(error),
}
}
}

@ -3,6 +3,7 @@
//! Inspired by [RDFjs](http://rdf.js.org/) and [Apache Commons RDF](http://commons.apache.org/proper/commons-rdf/)
mod blank_node;
mod error;
mod graph;
mod isomorphism;
mod literal;
@ -12,6 +13,7 @@ pub mod vocab;
pub(crate) mod xsd;
pub use crate::model::blank_node::BlankNode;
pub use crate::model::error::ModelError;
pub use crate::model::graph::SimpleGraph;
pub use crate::model::literal::Literal;
pub use crate::model::named_node::NamedNode;

@ -1,7 +1,8 @@
use crate::Result;
use crate::model::ModelError;
use rio_api::iri::Iri;
use rio_api::model as rio;
use std::fmt;
use std::result::Result;
/// A RDF [IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-iri)
///
@ -22,7 +23,7 @@ pub struct NamedNode {
impl NamedNode {
/// Builds and validate a RDF [IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-iri)
pub fn parse(iri: impl Into<String>) -> Result<Self> {
pub fn parse(iri: impl Into<String>) -> Result<Self, ModelError> {
Ok(Self::new_from_iri(Iri::parse(iri.into())?))
}

@ -7,8 +7,8 @@ use crate::sparql::plan::*;
use crate::sparql::ServiceHandler;
use crate::store::numeric_encoder::*;
use crate::store::StoreConnection;
use crate::Error;
use crate::Result;
use anyhow::anyhow;
use digest::Digest;
use md5::Md5;
use rand::random;
@ -220,8 +220,8 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
if let Some(graph_name) = get_pattern_value(graph_name, &tuple) {
graph_name
} else {
let result: EncodedTuplesIterator<'_> = Box::new(once(Err(anyhow!(
"Unknown graph name is not allowed when evaluating property path"
let result: EncodedTuplesIterator<'_> = Box::new(once(Err(Error::msg(
"Unknown graph name is not allowed when evaluating property path",
))));
return result;
};
@ -493,7 +493,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
) -> Result<EncodedTuplesIterator<'b>> {
let service_name = self.dataset.decode_named_node(
get_pattern_value(service_name, from)
.ok_or_else(|| anyhow!("The SERVICE name is not bound"))?,
.ok_or_else(|| Error::msg("The SERVICE name is not bound"))?,
)?;
Ok(self.encode_bindings(
variables,

@ -2,8 +2,8 @@
use crate::model::*;
use crate::sparql::model::*;
use crate::Error;
use crate::Result;
use anyhow::anyhow;
use std::io::Write;
pub fn write_json_results<W: Write>(results: QueryResult<'_>, mut sink: W) -> Result<W> {
@ -79,8 +79,8 @@ pub fn write_json_results<W: Write>(results: QueryResult<'_>, mut sink: W) -> Re
sink.write_all(b"]}}")?;
}
QueryResult::Graph(_) => {
return Err(anyhow!(
"Graphs could not be formatted to SPARQL query results XML format"
return Err(Error::msg(
"Graphs could not be formatted to SPARQL query results XML format",
));
}
}

@ -17,8 +17,8 @@ use crate::sparql::plan::TripleTemplate;
use crate::sparql::plan::{DatasetView, PlanNode};
use crate::sparql::plan_builder::PlanBuilder;
use crate::store::StoreConnection;
use crate::Error;
use crate::Result;
use anyhow::anyhow;
use rio_api::iri::Iri;
use std::fmt;
@ -180,7 +180,7 @@ struct EmptyServiceHandler;
impl ServiceHandler for EmptyServiceHandler {
fn handle<'a>(&'a self, _: &NamedNode, _: &'a GraphPattern) -> Result<BindingsIterator<'a>> {
Err(anyhow!("The SERVICE feature is not implemented"))
Err(Error::msg("The SERVICE feature is not implemented"))
}
}

@ -1,8 +1,8 @@
use crate::model::*;
use crate::sparql::json_results::write_json_results;
use crate::sparql::xml_results::{read_xml_results, write_xml_results};
use crate::Error;
use crate::{FileSyntax, GraphSyntax, Result};
use anyhow::anyhow;
use rand::random;
use rio_api::formatter::TriplesFormatter;
use rio_turtle::{NTriplesFormatter, TurtleFormatter};
@ -61,8 +61,8 @@ impl<'a> QueryResult<'a> {
}
})
} else {
Err(anyhow!(
"Bindings or booleans could not be formatted as an RDF graph"
Err(Error::msg(
"Bindings or booleans could not be formatted as an RDF graph",
))
}
}
@ -168,7 +168,7 @@ impl Variable {
pub fn name(&self) -> Result<&str> {
match self {
Variable::Variable { name } => Ok(name),
_ => Err(anyhow!("The variable {} has no name", self)),
_ => Err(Error::msg(format!("The variable {} has no name", self))),
}
}
}

@ -5,8 +5,8 @@ use crate::sparql::model::*;
use crate::sparql::plan::PlanPropertyPath;
use crate::sparql::plan::*;
use crate::store::numeric_encoder::{Encoder, ENCODED_DEFAULT_GRAPH};
use crate::Error;
use crate::Result;
use anyhow::anyhow;
use std::collections::HashSet;
pub struct PlanBuilder<E: Encoder> {
@ -654,7 +654,10 @@ impl<E: Encoder> PlanBuilder<E> {
"string",
)?
} else {
return Err(anyhow!("Not supported custom function {}", expression));
return Err(Error::msg(format!(
"Not supported custom function {}",
expression
)));
}
}
},
@ -680,7 +683,10 @@ impl<E: Encoder> PlanBuilder<E> {
graph_name,
)?)))
} else {
Err(anyhow!("The xsd:{} casting takes only one parameter", name))
Err(Error::msg(format!(
"The xsd:{} casting takes only one parameter",
name
)))
}
}

@ -2,8 +2,8 @@
use crate::model::*;
use crate::sparql::model::*;
use crate::Error;
use crate::Result;
use anyhow::anyhow;
use quick_xml::events::BytesDecl;
use quick_xml::events::BytesEnd;
use quick_xml::events::BytesStart;
@ -99,8 +99,8 @@ pub fn write_xml_results<W: Write>(results: QueryResult<'_>, sink: W) -> Result<
writer.write_event(Event::End(BytesEnd::borrowed(b"sparql")))?;
}
QueryResult::Graph(_) => {
return Err(anyhow!(
"Graphs could not be formatted to SPARQL query results XML format"
return Err(Error::msg(
"Graphs could not be formatted to SPARQL query results XML format",
));
}
}
@ -130,10 +130,10 @@ pub fn read_xml_results<'a>(source: impl BufRead + 'a) -> Result<QueryResult<'a>
let (ns, event) = reader.read_namespaced_event(&mut buffer, &mut namespace_buffer)?;
if let Some(ns) = ns {
if ns != b"http://www.w3.org/2005/sparql-results#".as_ref() {
return Err(anyhow!(
return Err(Error::msg(format!(
"Unexpected namespace found in RDF/XML query result: {}",
reader.decode(ns)?
));
)));
}
}
event
@ -144,14 +144,14 @@ pub fn read_xml_results<'a>(source: impl BufRead + 'a) -> Result<QueryResult<'a>
if event.name() == b"sparql" {
state = State::Sparql;
} else {
return Err(anyhow!("Expecting <sparql> tag, found {}", reader.decode(event.name())?));
return Err(Error::msg(format!("Expecting <sparql> tag, found {}", reader.decode(event.name())?)));
}
}
State::Sparql => {
if event.name() == b"head" {
state = State::Head;
} else {
return Err(anyhow!("Expecting <head> tag, found {}", reader.decode(event.name())?));
return Err(Error::msg(format!("Expecting <head> tag, found {}", reader.decode(event.name())?)));
}
}
State::Head => {
@ -159,12 +159,12 @@ pub fn read_xml_results<'a>(source: impl BufRead + 'a) -> Result<QueryResult<'a>
let name = event.attributes()
.filter_map(|attr| attr.ok())
.find(|attr| attr.key == b"name")
.ok_or_else(|| anyhow!("No name attribute found for the <variable> tag"))?;
.ok_or_else(|| Error::msg("No name attribute found for the <variable> tag"))?;
variables.push(name.unescape_and_decode_value(&reader)?);
} else if event.name() == b"link" {
// no op
} else {
return Err(anyhow!("Expecting <variable> or <link> tag, found {}", reader.decode(event.name())?));
return Err(Error::msg(format!("Expecting <variable> or <link> tag, found {}", reader.decode(event.name())?)));
}
}
State::AfterHead => {
@ -186,17 +186,17 @@ pub fn read_xml_results<'a>(source: impl BufRead + 'a) -> Result<QueryResult<'a>
}),
)));
} else if event.name() != b"link" && event.name() != b"results" && event.name() != b"boolean" {
return Err(anyhow!("Expecting sparql tag, found {}", reader.decode(event.name())?));
return Err(Error::msg(format!("Expecting sparql tag, found {}", reader.decode(event.name())?)));
}
}
State::Boolean => return Err(anyhow!("Unexpected tag inside of <boolean> tag: {}", reader.decode(event.name())?))
State::Boolean => return Err(Error::msg(format!("Unexpected tag inside of <boolean> tag: {}", reader.decode(event.name())?)))
},
Event::Empty(event) => match state {
State::Sparql => {
if event.name() == b"head" {
state = State::AfterHead;
} else {
return Err(anyhow!("Expecting <head> tag, found {}", reader.decode(event.name())?));
return Err(Error::msg(format!("Expecting <head> tag, found {}", reader.decode(event.name())?)));
}
}
State::Head => {
@ -204,12 +204,12 @@ pub fn read_xml_results<'a>(source: impl BufRead + 'a) -> Result<QueryResult<'a>
let name = event.attributes()
.filter_map(|v| v.ok())
.find(|attr| attr.key == b"name")
.ok_or_else(|| anyhow!("No name attribute found for the <variable> tag"))?;
.ok_or_else(|| Error::msg("No name attribute found for the <variable> tag"))?;
variables.push(name.unescape_and_decode_value(&reader)?);
} else if event.name() == b"link" {
// no op
} else {
return Err(anyhow!("Expecting <variable> or <link> tag, found {}", reader.decode(event.name())?));
return Err(Error::msg(format!("Expecting <variable> or <link> tag, found {}", reader.decode(event.name())?)));
}
},
State::AfterHead => {
@ -219,10 +219,10 @@ pub fn read_xml_results<'a>(source: impl BufRead + 'a) -> Result<QueryResult<'a>
Box::new(empty()),
)))
} else {
return Err(anyhow!("Unexpected autoclosing tag <{}>", reader.decode(event.name())?))
return Err(Error::msg(format!("Unexpected autoclosing tag <{}>", reader.decode(event.name())?)))
}
}
_ => return Err(anyhow!("Unexpected autoclosing tag <{}>", reader.decode(event.name())?))
_ => return Err(Error::msg(format!("Unexpected autoclosing tag <{}>", reader.decode(event.name())?)))
},
Event::Text(event) => {
let value = event.unescaped()?;
@ -233,18 +233,18 @@ pub fn read_xml_results<'a>(source: impl BufRead + 'a) -> Result<QueryResult<'a>
} else if value.as_ref() == b"false" {
Ok(QueryResult::Boolean(false))
} else {
Err(anyhow!("Unexpected boolean value. Found {}", reader.decode(&value)?))
Err(Error::msg(format!("Unexpected boolean value. Found {}", reader.decode(&value)?)))
};
}
_ => Err(anyhow!("Unexpected textual value found: {}", reader.decode(&value)?))
_ => Err(Error::msg(format!("Unexpected textual value found: {}", reader.decode(&value)?)))
};
},
Event::End(_) => if let State::Head = state {
state = State::AfterHead;
} else {
return Err(anyhow!("Unexpected early file end. All results file should have a <head> and a <result> or <boolean> tag"));
return Err(Error::msg("Unexpected early file end. All results file should have a <head> and a <result> or <boolean> tag"));
},
Event::Eof => return Err(anyhow!("Unexpected early file end. All results file should have a <head> and a <result> or <boolean> tag")),
Event::Eof => return Err(Error::msg("Unexpected early file end. All results file should have a <head> and a <result> or <boolean> tag")),
_ => (),
}
}
@ -292,10 +292,10 @@ impl<R: BufRead> ResultsIterator<R> {
.read_namespaced_event(&mut self.buffer, &mut self.namespace_buffer)?;
if let Some(ns) = ns {
if ns != b"http://www.w3.org/2005/sparql-results#".as_ref() {
return Err(anyhow!(
return Err(Error::msg(format!(
"Unexpected namespace found in RDF/XML query result: {}",
self.reader.decode(ns)?
));
)));
}
}
match event {
@ -304,10 +304,10 @@ impl<R: BufRead> ResultsIterator<R> {
if event.name() == b"result" {
state = State::Result;
} else {
return Err(anyhow!(
return Err(Error::msg(format!(
"Expecting <result>, found {}",
self.reader.decode(event.name())?
));
)));
}
}
State::Result => {
@ -319,23 +319,23 @@ impl<R: BufRead> ResultsIterator<R> {
{
Some(attr) => current_var = Some(attr.unescaped_value()?.to_vec()),
None => {
return Err(anyhow!(
"No name attribute found for the <binding> tag"
return Err(Error::msg(
"No name attribute found for the <binding> tag",
));
}
}
state = State::Binding;
} else {
return Err(anyhow!(
return Err(Error::msg(format!(
"Expecting <binding>, found {}",
self.reader.decode(event.name())?
));
)));
}
}
State::Binding => {
if term.is_some() {
return Err(anyhow!(
"There is already a value for the current binding"
return Err(Error::msg(
"There is already a value for the current binding",
));
}
if event.name() == b"uri" {
@ -356,10 +356,10 @@ impl<R: BufRead> ResultsIterator<R> {
}
state = State::Literal;
} else {
return Err(anyhow!(
return Err(Error::msg(format!(
"Expecting <uri>, <bnode> or <literal> found {}",
self.reader.decode(event.name())?
));
)));
}
}
_ => (),
@ -390,10 +390,10 @@ impl<R: BufRead> ResultsIterator<R> {
);
}
_ => {
return Err(anyhow!(
return Err(Error::msg(format!(
"Unexpected textual value found: {}",
self.reader.decode(&data)?
));
)));
}
}
}
@ -404,7 +404,7 @@ impl<R: BufRead> ResultsIterator<R> {
if let Some(var) = &current_var {
new_bindings[self.mapping[var]] = term.clone()
} else {
return Err(anyhow!("No name found for <binding> tag"));
return Err(Error::msg("No name found for <binding> tag"));
}
term = None;
state = State::Result;

@ -2,11 +2,9 @@ use crate::store::numeric_encoder::*;
use crate::store::*;
use crate::{Repository, Result};
use std::collections::{HashMap, HashSet};
use std::error::Error;
use std::fmt;
use std::hash::Hash;
use std::iter::{empty, once};
use std::sync::{PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard};
use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
/// Memory based implementation of the `Repository` trait.
/// It is cheap to build using the `MemoryRepository::default()` method.
@ -233,11 +231,11 @@ impl<'a> StoreTransaction for &'a MemoryStore {
impl MemoryStore {
fn indexes(&self) -> Result<RwLockReadGuard<'_, MemoryStoreIndexes>> {
Ok(self.indexes.read().map_err(MutexPoisonError::from)?)
Ok(self.indexes.read()?)
}
fn indexes_mut(&self) -> Result<RwLockWriteGuard<'_, MemoryStoreIndexes>> {
Ok(self.indexes.write().map_err(MutexPoisonError::from)?)
Ok(self.indexes.write()?)
}
fn quads<'a>(&'a self) -> Result<impl Iterator<Item = Result<EncodedQuad>> + 'a> {
@ -681,20 +679,3 @@ impl StoreTransaction for MemoryTransaction<'_> {
Ok(())
}
}
#[derive(Debug)]
struct MutexPoisonError {}
impl fmt::Display for MutexPoisonError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Mutex was poisoned")
}
}
impl Error for MutexPoisonError {}
impl<T> From<PoisonError<T>> for MutexPoisonError {
fn from(_: PoisonError<T>) -> Self {
Self {}
}
}

@ -14,7 +14,7 @@ use crate::model::*;
use crate::repository::RepositoryTransaction;
use crate::sparql::{QueryOptions, SimplePreparedQuery};
use crate::store::numeric_encoder::*;
use crate::{DatasetSyntax, GraphSyntax, RepositoryConnection, Result};
use crate::{DatasetSyntax, Error, GraphSyntax, RepositoryConnection, Result};
use rio_api::parser::{QuadsParser, TriplesParser};
use rio_turtle::{NQuadsParser, NTriplesParser, TriGParser, TurtleParser};
use rio_xml::RdfXmlParser;
@ -226,7 +226,7 @@ impl<T: StoreTransaction> StoreRepositoryTransaction<T> {
to_graph_name: Option<&NamedOrBlankNode>,
) -> Result<()>
where
P::Error: Send + Sync + 'static,
Error: From<P::Error>,
{
let mut bnode_map = HashMap::default();
let graph_name = if let Some(graph_name) = to_graph_name {
@ -244,7 +244,7 @@ impl<T: StoreTransaction> StoreRepositoryTransaction<T> {
fn load_from_quad_parser<P: QuadsParser>(&mut self, mut parser: P) -> Result<()>
where
P::Error: Send + Sync + 'static,
Error: From<P::Error>,
{
let mut bnode_map = HashMap::default();
parser.parse_all(&mut move |q| {

@ -2,8 +2,8 @@ use crate::model::vocab::rdf;
use crate::model::vocab::xsd;
use crate::model::xsd::*;
use crate::model::*;
use crate::Error;
use crate::Result;
use anyhow::anyhow;
use md5::digest::Digest;
use md5::Md5;
use rand::random;
@ -604,7 +604,7 @@ impl<R: Read> TermReader for R {
buffer,
)))
}
_ => Err(anyhow!("the term buffer has an invalid type id")),
_ => Err(Error::msg("the term buffer has an invalid type id")),
}
}
@ -1106,17 +1106,21 @@ pub trait Decoder {
match self.decode_term(encoded)? {
Term::NamedNode(named_node) => Ok(named_node.into()),
Term::BlankNode(blank_node) => Ok(blank_node.into()),
Term::Literal(_) => Err(anyhow!("A literal has ben found instead of a named node")),
Term::Literal(_) => Err(Error::msg(
"A literal has ben found instead of a named node",
)),
}
}
fn decode_named_node(&self, encoded: EncodedTerm) -> Result<NamedNode> {
match self.decode_term(encoded)? {
Term::NamedNode(named_node) => Ok(named_node),
Term::BlankNode(_) => Err(anyhow!(
"A blank node has been found instead of a named node"
Term::BlankNode(_) => Err(Error::msg(
"A blank node has been found instead of a named node",
)),
Term::Literal(_) => Err(Error::msg(
"A literal has ben found instead of a named node",
)),
Term::Literal(_) => Err(anyhow!("A literal has ben found instead of a named node")),
}
}
@ -1144,7 +1148,9 @@ pub trait Decoder {
impl<S: StrLookup> Decoder for S {
fn decode_term(&self, encoded: EncodedTerm) -> Result<Term> {
match encoded {
EncodedTerm::DefaultGraph => Err(anyhow!("The default graph tag is not a valid term")),
EncodedTerm::DefaultGraph => {
Err(Error::msg("The default graph tag is not a valid term"))
}
EncodedTerm::NamedNode { iri_id } => {
Ok(NamedNode::new_unchecked(get_required_str(self, iri_id)?).into())
}
@ -1183,10 +1189,10 @@ impl<S: StrLookup> Decoder for S {
fn get_required_str(lookup: &impl StrLookup, id: u128) -> Result<String> {
lookup.get_str(id)?.ok_or_else(|| {
anyhow!(
Error::msg(format!(
"Not able to find the string with id {} in the string store",
id
)
))
})
}

@ -1,7 +1,7 @@
use crate::store::numeric_encoder::*;
use crate::store::{Store, StoreConnection, StoreRepositoryConnection, StoreTransaction};
use crate::Error;
use crate::{Repository, Result};
use anyhow::anyhow;
use rocksdb::*;
use std::io::Cursor;
use std::iter::{empty, once};
@ -596,7 +596,7 @@ impl RocksDbStoreInnerTransaction<'_> {
fn get_cf<'a>(db: &'a DB, name: &str) -> Result<&'a ColumnFamily> {
db.cf_handle(name)
.ok_or_else(|| anyhow!("column family {} not found", name))
.ok_or_else(|| Error::msg(format!("column family {} not found", name)))
}
fn wrap_error<'a, E: 'a, I: Iterator<Item = Result<E>> + 'a>(

@ -1,9 +1,6 @@
use anyhow::anyhow;
use oxigraph::model::*;
use oxigraph::sparql::{
BindingsIterator, GraphPattern, PreparedQuery, QueryOptions, QueryResult, ServiceHandler,
};
use oxigraph::{GraphSyntax, MemoryRepository, Repository, RepositoryConnection, Result};
use oxigraph::sparql::*;
use oxigraph::*;
use std::io::BufRead;
#[test]
@ -73,7 +70,7 @@ fn two_service_test() {
.as_ref();
do_pattern(triples, graph_pattern, QueryOptions::default())
} else {
Err(anyhow!("not found"))
Err(Error::msg("not found"))
}
}
}
@ -124,7 +121,7 @@ fn silent_service_empty_set_test() {
_: &NamedNode,
_: &'a GraphPattern,
) -> Result<BindingsIterator<'a>> {
Err(anyhow!("This is supposed to fail"))
Err(Error::msg("This is supposed to fail"))
}
}
@ -162,7 +159,7 @@ fn non_silent_service_test() {
_: &NamedNode,
_: &'a GraphPattern,
) -> Result<BindingsIterator<'a>> {
Err(anyhow!("This is supposed to fail"))
Err(Error::msg("This is supposed to fail"))
}
}
@ -232,7 +229,7 @@ fn query_repository<'a>(
Box::new(collected.into_iter()),
))
}
_ => Err(anyhow!("Excpected bindings but got another QueryResult")),
_ => Err(Error::msg("Excpected bindings but got another QueryResult")),
}
}
@ -254,7 +251,7 @@ fn pattern_repository<'a>(
Box::new(collected.into_iter()),
))
}
_ => Err(anyhow!("Expected bindings but got another QueryResult")),
_ => Err(Error::msg("Expected bindings but got another QueryResult")),
}
}

@ -1,5 +1,4 @@
///! Integration tests based on [SPARQL 1.1 Test Cases](https://www.w3.org/2009/sparql/docs/tests/README.html)
use anyhow::anyhow;
use oxigraph::model::vocab::rdf;
use oxigraph::model::vocab::rdfs;
use oxigraph::model::*;
@ -162,33 +161,33 @@ fn sparql_w3c_query_evaluation_testsuite() -> Result<()> {
.connection()?
.prepare_query(&read_file_to_string(&test.query)?, QueryOptions::default().with_base_iri(&test.query).with_service_handler(StaticServiceHandler::new(&test.service_data)?))
{
Err(error) => Err(anyhow!(
Err(error) => Err(Error::msg(format!(
"Failure to parse query of {} with error: {}",
test, error
)),
))),
Ok(query) => match query.exec() {
Err(error) => Err(anyhow!(
Err(error) => Err(Error::msg(format!(
"Failure to execute query of {} with error: {}",
test, error
)),
))),
Ok(result) => {
let expected_graph =
load_sparql_query_result_graph(test.result.as_ref().unwrap()).map_err(|e| anyhow!("Error constructing expected graph for {}: {}", test, e))?;
load_sparql_query_result_graph(test.result.as_ref().unwrap()).map_err(|e| Error::msg(format!("Error constructing expected graph for {}: {}", test, e)))?;
let with_order = expected_graph
.triples_for_predicate(&rs::INDEX)
.next()
.is_some();
let actual_graph = to_graph(result, with_order).map_err(|e| anyhow!("Error constructing result graph for {}: {}", test, e))?;
let actual_graph = to_graph(result, with_order).map_err(|e| Error::msg(format!("Error constructing result graph for {}: {}", test, e)))?;
if actual_graph.is_isomorphic(&expected_graph) {
Ok(())
} else {
Err(anyhow!("Failure on {}.\nExpected file:\n{}\nOutput file:\n{}\nParsed query:\n{}\nData:\n{}\n",
Err(Error::msg(format!("Failure on {}.\nExpected file:\n{}\nOutput file:\n{}\nParsed query:\n{}\nData:\n{}\n",
test,
expected_graph,
actual_graph,
Query::parse(&read_file_to_string(&test.query)?, Some(&test.query)).unwrap(),
repository_to_string(&repository)
))
)))
}
}
},
@ -240,7 +239,10 @@ fn load_graph_to_repository(
} else if url.ends_with(".rdf") {
GraphSyntax::RdfXml
} else {
return Err(anyhow!("Serialization type not found for {}", url));
return Err(Error::msg(format!(
"Serialization type not found for {}",
url
)));
};
connection.load_graph(read_file(url)?, syntax, to_graph_name, Some(url))
}
@ -276,7 +278,7 @@ fn to_relative_path(url: &str) -> Result<String> {
"rdf-tests/sparql11/",
))
} else {
Err(anyhow!("Not supported url for file: {}", url))
Err(Error::msg(format!("Not supported url for file: {}", url)))
}
}
@ -286,7 +288,11 @@ fn read_file(url: &str) -> Result<impl BufRead> {
base_path.push(to_relative_path(url)?);
Ok(BufReader::new(File::open(&base_path).map_err(|e| {
anyhow!("Opening file {} failed with {}", base_path.display(), e)
Error::msg(format!(
"Opening file {} failed with {}",
base_path.display(),
e,
))
})?))
}
@ -528,8 +534,8 @@ impl Iterator for TestManifest {
let n = n.clone().into();
let query = match self.graph.object_for_subject_predicate(&n, &qt::QUERY) {
Some(Term::NamedNode(q)) => q.as_str().to_owned(),
Some(_) => return Some(Err(anyhow!("invalid query"))),
None => return Some(Err(anyhow!("query not found"))),
Some(_) => return Some(Err(Error::msg("invalid query"))),
None => return Some(Err(Error::msg("query not found"))),
};
let data = match self.graph.object_for_subject_predicate(&n, &qt::DATA) {
Some(Term::NamedNode(q)) => Some(q.as_str().to_owned()),
@ -567,9 +573,12 @@ impl Iterator for TestManifest {
.collect();
(query, data, graph_data, service_data)
}
Some(_) => return Some(Err(anyhow!("invalid action"))),
Some(_) => return Some(Err(Error::msg("invalid action"))),
None => {
return Some(Err(anyhow!("action not found for test {}", test_subject)));
return Some(Err(Error::msg(format!(
"action not found for test {}",
test_subject
))));
}
};
let result = match self
@ -577,7 +586,7 @@ impl Iterator for TestManifest {
.object_for_subject_predicate(&test_subject, &*mf::RESULT)
{
Some(Term::NamedNode(n)) => Some(n.as_str().to_owned()),
Some(_) => return Some(Err(anyhow!("invalid result"))),
Some(_) => return Some(Err(Error::msg("invalid result"))),
None => None,
};
Some(Ok(Test {
@ -592,7 +601,7 @@ impl Iterator for TestManifest {
result,
}))
}
Some(_) => Some(Err(anyhow!("invalid test list"))),
Some(_) => Some(Err(Error::msg("invalid test list"))),
None => {
match self.manifests_to_do.pop() {
Some(url) => {
@ -617,7 +626,7 @@ impl Iterator for TestManifest {
}),
);
}
Some(_) => return Some(Err(anyhow!("invalid tests list"))),
Some(_) => return Some(Err(Error::msg("invalid tests list"))),
None => (),
}
@ -633,7 +642,10 @@ impl Iterator for TestManifest {
));
}
Some(term) => {
return Some(Err(anyhow!("Invalid tests list. Got term {}", term)));
return Some(Err(Error::msg(format!(
"Invalid tests list. Got term {}",
term
))));
}
None => (),
}
@ -717,7 +729,7 @@ impl ServiceHandler for StaticServiceHandler {
if let QueryResult::Bindings(iterator) = self
.services
.get(service_name)
.ok_or_else(|| anyhow!("Service {} not found", service_name))?
.ok_or_else(|| Error::msg(format!("Service {} not found", service_name)))?
.connection()?
.prepare_query_from_pattern(
&graph_pattern,
@ -733,7 +745,7 @@ impl ServiceHandler for StaticServiceHandler {
Box::new(collected.into_iter()),
))
} else {
Err(anyhow!("Expected bindings but got another QueryResult"))
Err(Error::msg("Expected bindings but got another QueryResult"))
}
}
}

@ -16,4 +16,4 @@ clap = "2"
rouille = "3"
reqwest = "0.9"
serde_json = "1"
chrono = "0.4"
chrono = "0.4"

@ -30,8 +30,9 @@ impl<R: Repository + Copy> WikibaseLoader<R> {
) -> Result<Self> {
Ok(Self {
repository,
api_url: Url::parse(api_url)?,
entity_data_url: Url::parse(&(pages_base_url.to_owned() + "Special:EntityData"))?,
api_url: Url::parse(api_url).map_err(Error::wrap)?,
entity_data_url: Url::parse(&(pages_base_url.to_owned() + "Special:EntityData"))
.map_err(Error::wrap)?,
client: Client::new(),
namespaces: namespaces.to_vec(),
start: Utc::now(),
@ -176,9 +177,12 @@ impl<R: Repository + Copy> WikibaseLoader<R> {
.get(self.api_url.clone())
.query(parameters)
.header(USER_AGENT, SERVER)
.send()?
.error_for_status()?
.json()?)
.send()
.map_err(Error::wrap)?
.error_for_status()
.map_err(Error::wrap)?
.json()
.map_err(Error::wrap)?)
}
fn get_entity_data(&self, id: &str) -> Result<impl Read> {
@ -187,8 +191,10 @@ impl<R: Repository + Copy> WikibaseLoader<R> {
.get(self.entity_data_url.clone())
.query(&[("id", id), ("format", "nt"), ("flavor", "dump")])
.header(USER_AGENT, SERVER)
.send()?
.error_for_status()?)
.send()
.map_err(Error::wrap)?
.error_for_status()
.map_err(Error::wrap)?)
}
fn load_entity_data(&self, uri: &str, data: impl Read) -> Result<()> {
@ -208,6 +214,7 @@ impl<R: Repository + Copy> WikibaseLoader<R> {
Some(&NamedNode::parse(uri)?.into()),
None,
)
})
})?;
Ok(())
}
}

Loading…
Cancel
Save