Uses io::Error for all basic disk store operations

pull/46/head
Tpt 4 years ago
parent 562cda7d97
commit 0d4743f452
  1. 40
      lib/src/error.rs
  2. 7
      lib/src/lib.rs
  3. 7
      lib/src/sparql/eval.rs
  4. 2
      lib/src/sparql/mod.rs
  5. 18
      lib/src/sparql/model.rs
  6. 3
      lib/src/sparql/parser.rs
  7. 56
      lib/src/sparql/plan.rs
  8. 4
      lib/src/sparql/plan_builder.rs
  9. 72
      lib/src/store/memory.rs
  10. 66
      lib/src/store/mod.rs
  11. 104
      lib/src/store/numeric_encoder.rs
  12. 158
      lib/src/store/rocksdb.rs
  13. 137
      lib/src/store/sled.rs
  14. 22
      python/src/sled_store.rs
  15. 2
      wikibase/src/loader.rs

@ -2,7 +2,6 @@ use crate::model::{BlankNodeIdParseError, IriParseError, LanguageTagParseError};
use crate::sparql::SparqlParseError;
use rio_turtle::TurtleError;
use rio_xml::RdfXmlError;
use std::convert::Infallible;
use std::error;
use std::fmt;
use std::io;
@ -78,6 +77,12 @@ impl From<Infallible> for Error {
}
}
impl From<std::convert::Infallible> for Error {
fn from(error: std::convert::Infallible) -> Self {
match error {}
}
}
impl From<io::Error> for Error {
fn from(error: io::Error) -> Self {
Self {
@ -142,17 +147,34 @@ impl From<SparqlParseError> for Error {
}
}
#[cfg(feature = "rocksdb")]
impl From<rocksdb::Error> for Error {
fn from(error: rocksdb::Error) -> Self {
Self::wrap(error)
//TODO: convert to "!" when "never_type" is going to be stabilized
#[allow(clippy::empty_enum)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub(crate) enum Infallible {}
impl fmt::Display for Infallible {
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {}
}
}
#[cfg(feature = "sled")]
impl From<sled::Error> for Error {
fn from(error: sled::Error) -> Self {
Self::wrap(error)
impl std::error::Error for Infallible {}
impl From<Infallible> for std::convert::Infallible {
fn from(error: Infallible) -> Self {
match error {}
}
}
impl From<std::convert::Infallible> for Infallible {
fn from(error: std::convert::Infallible) -> Self {
match error {}
}
}
impl From<Infallible> for std::io::Error {
fn from(error: Infallible) -> Self {
match error {}
}
}

@ -15,10 +15,9 @@
//! Usage example with the `MemoryStore`:
//!
//! ```
//! use oxigraph::MemoryStore;
//! use oxigraph::model::*;
//! use oxigraph::{MemoryStore, Result};
//! use crate::oxigraph::sparql::QueryOptions;
//! use oxigraph::sparql::QueryResult;
//! use oxigraph::sparql::{QueryOptions, QueryResult};
//!
//! let store = MemoryStore::new();
//!
@ -35,7 +34,7 @@
//! if let QueryResult::Solutions(mut solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default())? {
//! assert_eq!(solutions.next().unwrap()?.get("s"), Some(&ex.into()));
//! }
//! # Result::Ok(())
//! # oxigraph::Result::Ok(())
//! ```
#![deny(
future_incompatible,

@ -2396,7 +2396,12 @@ impl<S: ReadableEncodedStore + 'static> Iterator for DescribeIterator<S> {
loop {
if let Some(quad) = self.quads.next() {
return Some(match quad {
Ok(quad) => self.eval.dataset.decode_quad(&quad).map(|q| q.into()),
Ok(quad) => self
.eval
.dataset
.decode_quad(&quad)
.map(|q| q.into())
.map_err(|e| e.into()),
Err(error) => Err(error),
});
}

@ -146,8 +146,8 @@ impl<S: ReadableEncodedStore + 'static> SimplePreparedQuery<S> {
/// Might be used to implement [SPARQL 1.1 Federated Query](https://www.w3.org/TR/sparql11-federated-query/)
///
/// ```
/// use oxigraph::model::*;
/// use oxigraph::{MemoryStore, Result};
/// use oxigraph::model::*;
/// use oxigraph::sparql::{QueryOptions, QueryResult, ServiceHandler, Query};
///
/// #[derive(Default)]

@ -37,8 +37,8 @@ impl QueryResult {
/// This method fails if it is called on the `Graph` results
///
/// ```
/// use oxigraph::MemoryStore;
/// use oxigraph::model::*;
/// use oxigraph::{MemoryStore, Result};
/// use oxigraph::sparql::{QueryOptions, QueryResultSyntax};
///
/// let store = MemoryStore::new();
@ -48,7 +48,7 @@ impl QueryResult {
/// let mut results = Vec::new();
/// store.query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default())?.write(&mut results, QueryResultSyntax::Json)?;
/// assert_eq!(results, "{\"head\":{\"vars\":[\"s\"]},\"results\":{\"bindings\":[{\"s\":{\"type\":\"uri\",\"value\":\"http://example.com\"}}]}}".as_bytes());
/// # Result::Ok(())
/// # oxigraph::Result::Ok(())
/// ```
pub fn write(self, writer: &mut impl Write, syntax: QueryResultSyntax) -> Result<()> {
match syntax {
@ -62,9 +62,9 @@ impl QueryResult {
/// This method fails if it is called on the `Solution` or `Boolean` results
///
/// ```
/// use oxigraph::model::*;
/// use oxigraph::{MemoryStore, Result, GraphSyntax};
/// use oxigraph::{MemoryStore, GraphSyntax};
/// use oxigraph::sparql::QueryOptions;
/// use oxigraph::model::*;
/// use std::io::Cursor;
///
/// let graph = "<http://example.com> <http://example.com> <http://example.com> .\n".as_bytes();
@ -75,7 +75,7 @@ impl QueryResult {
/// let mut results = Vec::new();
/// store.query("CONSTRUCT WHERE { ?s ?p ?o }", QueryOptions::default())?.write_graph(&mut results, GraphSyntax::NTriples)?;
/// assert_eq!(results, graph);
/// # Result::Ok(())
/// # oxigraph::Result::Ok(())
/// ```
pub fn write_graph(self, write: &mut impl Write, syntax: GraphSyntax) -> Result<()> {
if let QueryResult::Graph(triples) = self {
@ -162,7 +162,7 @@ impl FileSyntax for QueryResultSyntax {
/// An iterator over query result solutions
///
/// ```
/// use oxigraph::{MemoryStore, Result};
/// use oxigraph::MemoryStore;
/// use oxigraph::sparql::{QueryResult, QueryOptions};
///
/// let store = MemoryStore::new();
@ -171,7 +171,7 @@ impl FileSyntax for QueryResultSyntax {
/// println!("{:?}", solution?.get("s"));
/// }
/// }
/// # Result::Ok(())
/// # oxigraph::Result::Ok(())
/// ```
pub struct QuerySolutionsIterator {
variables: Rc<Vec<Variable>>,
@ -189,14 +189,14 @@ impl QuerySolutionsIterator {
/// The variables used in the solutions
///
/// ```
/// use oxigraph::{MemoryStore, Result};
/// use oxigraph::MemoryStore;
/// use oxigraph::sparql::{QueryResult, QueryOptions, Variable};
///
/// let store = MemoryStore::new();
/// if let QueryResult::Solutions(solutions) = store.query("SELECT ?s ?o WHERE { ?s ?p ?o }", QueryOptions::default())? {
/// assert_eq!(solutions.variables(), &[Variable::new("s"), Variable::new("o")]);
/// }
/// # Result::Ok(())
/// # oxigraph::Result::Ok(())
/// ```
pub fn variables(&self) -> &[Variable] {
&*self.variables

@ -19,14 +19,13 @@ use std::{char, fmt};
/// A parsed [SPARQL query](https://www.w3.org/TR/sparql11-query/)
///
/// ```
/// # use oxigraph::Result;
/// use oxigraph::sparql::Query;
///
/// let query_str = "SELECT ?s ?p ?o WHERE { ?s ?p ?o . }";
/// let query = Query::parse(query_str, None)?;
///
/// assert_eq!(query.to_string(), query_str);
/// # Result::Ok(())
/// # oxigraph::Result::Ok(())
/// ```
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct Query(pub(crate) QueryVariants);

@ -9,6 +9,7 @@ use crate::store::ReadableEncodedStore;
use crate::Result;
use std::cell::{RefCell, RefMut};
use std::collections::BTreeSet;
use std::io;
use std::rc::Rc;
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
@ -583,32 +584,35 @@ impl<S: ReadableEncodedStore> DatasetView<S> {
) -> Box<dyn Iterator<Item = Result<EncodedQuad>>> {
if graph_name == None {
Box::new(
self.store
.encoded_quads_for_pattern(subject, predicate, object, None)
.filter(|quad| match quad {
Err(_) => true,
Ok(quad) => quad.graph_name != ENCODED_DEFAULT_GRAPH,
}),
map_io_err(
self.store
.encoded_quads_for_pattern(subject, predicate, object, None),
)
.filter(|quad| match quad {
Err(_) => true,
Ok(quad) => quad.graph_name != ENCODED_DEFAULT_GRAPH,
}),
)
} else if graph_name == Some(ENCODED_DEFAULT_GRAPH) && self.default_graph_as_union {
Box::new(
self.store
.encoded_quads_for_pattern(subject, predicate, object, None)
.map(|quad| {
let quad = quad?;
Ok(EncodedQuad::new(
quad.subject,
quad.predicate,
quad.object,
ENCODED_DEFAULT_GRAPH,
))
}),
map_io_err(
self.store
.encoded_quads_for_pattern(subject, predicate, object, None),
)
.map(|quad| {
let quad = quad?;
Ok(EncodedQuad::new(
quad.subject,
quad.predicate,
quad.object,
ENCODED_DEFAULT_GRAPH,
))
}),
)
} else {
Box::new(
self.store
.encoded_quads_for_pattern(subject, predicate, object, graph_name),
)
Box::new(map_io_err(self.store.encoded_quads_for_pattern(
subject, predicate, object, graph_name,
)))
}
}
@ -620,8 +624,14 @@ impl<S: ReadableEncodedStore> DatasetView<S> {
}
}
fn map_io_err<'a, T>(
iter: impl Iterator<Item = std::result::Result<T, impl Into<io::Error>>> + 'a,
) -> impl Iterator<Item = Result<T>> + 'a {
iter.map(|e| e.map_err(|e| e.into().into()))
}
impl<S: ReadableEncodedStore> StrLookup for DatasetView<S> {
type Error = S::Error;
type Error = <S as StrLookup>::Error;
fn get_str(&self, id: StrHash) -> std::result::Result<Option<String>, Self::Error> {
if let Some(value) = self.extra.borrow().get_str(id).unwrap_infallible() {
@ -638,7 +648,7 @@ struct DatasetViewStrContainer<'a, S: ReadableEncodedStore> {
}
impl<'a, S: ReadableEncodedStore> StrContainer for DatasetViewStrContainer<'a, S> {
type Error = S::Error;
type Error = <S as StrLookup>::Error;
fn insert_str(&mut self, key: StrHash, value: &str) -> std::result::Result<(), Self::Error> {
if self.store.get_str(key)?.is_none() {

@ -8,7 +8,7 @@ use crate::Result;
use std::collections::{BTreeSet, HashSet};
use std::rc::Rc;
pub struct PlanBuilder<E: Encoder> {
pub(crate) struct PlanBuilder<E: Encoder> {
encoder: E,
}
@ -270,7 +270,7 @@ impl<E: Encoder> PlanBuilder<E> {
PropertyPath::NegatedPropertySet(p) => PlanPropertyPath::NegatedPropertySet(Rc::new(
p.iter()
.map(|p| self.encoder.encode_named_node(p).map_err(|e| e.into()))
.collect::<Result<Vec<_>>>()?,
.collect::<std::result::Result<Vec<_>, _>>()?,
)),
})
}

@ -1,6 +1,6 @@
//! In-memory store.
use crate::error::UnwrapInfallible;
use crate::error::{Infallible, UnwrapInfallible};
use crate::model::*;
use crate::sparql::{Query, QueryOptions, QueryResult, SimplePreparedQuery};
use crate::store::numeric_encoder::*;
@ -10,14 +10,14 @@ use crate::store::{
use crate::{DatasetSyntax, Error, GraphSyntax};
use std::collections::hash_map::DefaultHasher;
use std::collections::{HashMap, HashSet};
use std::convert::{Infallible, TryInto};
use std::fmt;
use std::convert::TryInto;
use std::hash::{BuildHasherDefault, Hash, Hasher};
use std::io::{BufRead, Write};
use std::iter::FromIterator;
use std::mem::size_of;
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
use std::vec::IntoIter;
use std::{fmt, io};
/// In-memory store.
/// It encodes a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) and allows to query and update it using SPARQL.
@ -25,8 +25,8 @@ use std::vec::IntoIter;
///
/// Usage example:
/// ```
/// use oxigraph::MemoryStore;
/// use oxigraph::model::*;
/// use oxigraph::{MemoryStore, Result};
/// use oxigraph::sparql::{QueryResult, QueryOptions};
///
/// let store = MemoryStore::new();
@ -44,7 +44,7 @@ use std::vec::IntoIter;
/// if let QueryResult::Solutions(mut solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default())? {
/// assert_eq!(solutions.next().unwrap()?.get("s"), Some(&ex.into()));
/// }
/// # Result::Ok(())
/// # oxigraph::Result::Ok(())
/// ```
#[derive(Clone)]
pub struct MemoryStore {
@ -87,9 +87,9 @@ impl MemoryStore {
///
/// Usage example:
/// ```
/// use oxigraph::MemoryStore;
/// use oxigraph::model::*;
/// use oxigraph::{MemoryStore, Result};
/// use oxigraph::sparql::{QueryOptions, QueryResult};
/// use oxigraph::sparql::{QueryResult, QueryOptions};
///
/// let store = MemoryStore::new();
///
@ -101,7 +101,7 @@ impl MemoryStore {
/// if let QueryResult::Solutions(mut solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default())? {
/// assert_eq!(solutions.next().unwrap()?.get("s"), Some(&ex.into()));
/// }
/// # Result::Ok(())
/// # oxigraph::Result::Ok(())
/// ```
pub fn query(
&self,
@ -116,9 +116,9 @@ impl MemoryStore {
///
/// Usage example:
/// ```
/// use oxigraph::MemoryStore;
/// use oxigraph::model::*;
/// use oxigraph::{MemoryStore, Result};
/// use oxigraph::sparql::{QueryOptions, QueryResult};
/// use oxigraph::sparql::{QueryResult, QueryOptions};
///
/// let store = MemoryStore::new();
///
@ -131,7 +131,7 @@ impl MemoryStore {
/// if let QueryResult::Solutions(mut solutions) = prepared_query.exec()? {
/// assert_eq!(solutions.next().unwrap()?.get("s"), Some(&ex.into()));
/// }
/// # Result::Ok(())
/// # oxigraph::Result::Ok(())
/// ```
pub fn prepare_query(
&self,
@ -149,8 +149,8 @@ impl MemoryStore {
///
/// Usage example:
/// ```
/// use oxigraph::MemoryStore;
/// use oxigraph::model::*;
/// use oxigraph::{MemoryStore, Result};
///
/// let store = MemoryStore::new();
///
@ -162,7 +162,7 @@ impl MemoryStore {
/// // quad filter
/// let results: Vec<Quad> = store.quads_for_pattern(None, None, None, None).collect();
/// assert_eq!(vec![quad], results);
/// # Result::Ok(())
/// # oxigraph::Result::Ok(())
/// ```
pub fn quads_for_pattern(
&self,
@ -214,8 +214,9 @@ impl MemoryStore {
///
/// Usage example:
/// ```
/// use oxigraph::MemoryStore;
/// use oxigraph::model::*;
/// use oxigraph::{MemoryStore, Result};
/// use std::convert::Infallible;
///
/// let store = MemoryStore::new();
///
@ -225,17 +226,17 @@ impl MemoryStore {
/// // transaction
/// store.transaction(|transaction| {
/// transaction.insert(quad.clone());
/// Ok(())
/// Ok(()) as Result<(),Infallible>
/// })?;
///
/// // quad filter
/// assert!(store.contains(&quad));
/// # Result::Ok(())
/// # oxigraph::Result::Ok(())
/// ```
pub fn transaction<'a>(
pub fn transaction<'a, E>(
&'a self,
f: impl FnOnce(&mut MemoryTransaction<'a>) -> crate::Result<()>,
) -> crate::Result<()> {
f: impl FnOnce(&mut MemoryTransaction<'a>) -> Result<(), E>,
) -> Result<(), E> {
let mut transaction = MemoryTransaction {
store: self,
ops: Vec::new(),
@ -250,8 +251,8 @@ impl MemoryStore {
///
/// Usage example:
/// ```
/// use oxigraph::{MemoryStore, GraphSyntax};
/// use oxigraph::model::*;
/// use oxigraph::{MemoryStore, Result, GraphSyntax};
///
/// let store = MemoryStore::new();
///
@ -263,7 +264,7 @@ impl MemoryStore {
/// let results: Vec<Quad> = store.quads_for_pattern(None, None, None, None).collect();
/// let ex = NamedNode::new("http://example.com")?;
/// assert_eq!(vec![Quad::new(ex.clone(), ex.clone(), ex.clone(), None)], results);
/// # Result::Ok(())
/// # oxigraph::Result::Ok(())
/// ```
pub fn load_graph(
&self,
@ -280,8 +281,8 @@ impl MemoryStore {
///
/// Usage example:
/// ```
/// use oxigraph::{MemoryStore, DatasetSyntax};
/// use oxigraph::model::*;
/// use oxigraph::{MemoryStore, Result, DatasetSyntax};
///
/// let store = MemoryStore::new();
///
@ -293,7 +294,7 @@ impl MemoryStore {
/// let results: Vec<Quad> = store.quads_for_pattern(None, None, None, None).collect();
/// let ex = NamedNode::new("http://example.com")?;
/// assert_eq!(vec![Quad::new(ex.clone(), ex.clone(), ex.clone(), Some(ex.into()))], results);
/// # Result::Ok(())
/// # oxigraph::Result::Ok(())
/// ```
pub fn load_dataset(
&self,
@ -334,8 +335,8 @@ impl MemoryStore {
///
/// Usage example:
/// ```
/// use oxigraph::{MemoryStore, GraphSyntax};
/// use oxigraph::model::GraphName;
/// use oxigraph::{MemoryStore, Result, GraphSyntax};
///
/// let file = "<http://example.com> <http://example.com> <http://example.com> .\n".as_bytes();
///
@ -345,14 +346,14 @@ impl MemoryStore {
/// let mut buffer = Vec::new();
/// store.dump_graph(&mut buffer, GraphSyntax::NTriples, &GraphName::DefaultGraph)?;
/// assert_eq!(file, buffer.as_slice());
/// # Result::Ok(())
/// # oxigraph::Result::Ok(())
/// ```
pub fn dump_graph(
&self,
writer: &mut impl Write,
syntax: GraphSyntax,
from_graph_name: &GraphName,
) -> crate::Result<()> {
) -> Result<(), io::Error> {
dump_graph(
self.quads_for_pattern(None, None, None, Some(from_graph_name))
.map(|q| Ok(q.into())),
@ -365,7 +366,7 @@ impl MemoryStore {
///
/// Usage example:
/// ```
/// use oxigraph::{MemoryStore, Result, DatasetSyntax};
/// use oxigraph::{MemoryStore, DatasetSyntax};
///
/// let file = "<http://example.com> <http://example.com> <http://example.com> <http://example.com> .\n".as_bytes();
///
@ -375,13 +376,13 @@ impl MemoryStore {
/// let mut buffer = Vec::new();
/// store.dump_dataset(&mut buffer, DatasetSyntax::NQuads)?;
/// assert_eq!(file, buffer.as_slice());
/// # Result::Ok(())
/// # oxigraph::Result::Ok(())
/// ```
pub fn dump_dataset(
&self,
writer: &mut impl Write,
syntax: DatasetSyntax,
) -> crate::Result<()> {
) -> Result<(), io::Error> {
dump_dataset(
self.quads_for_pattern(None, None, None, None).map(Ok),
writer,
@ -718,6 +719,7 @@ impl StrContainer for MemoryStoreIndexes {
}
impl<'a> ReadableEncodedStore for MemoryStore {
type Error = Infallible;
type QuadsIter = EncodedQuadsIter;
fn encoded_quads_for_pattern(
@ -961,8 +963,8 @@ impl<'a> MemoryTransaction<'a> {
///
/// Usage example:
/// ```
/// use oxigraph::{MemoryStore, GraphSyntax};
/// use oxigraph::model::*;
/// use oxigraph::{MemoryStore, Result, GraphSyntax};
///
/// let store = MemoryStore::new();
///
@ -976,7 +978,7 @@ impl<'a> MemoryTransaction<'a> {
/// let results: Vec<Quad> = store.quads_for_pattern(None, None, None, None).collect();
/// let ex = NamedNode::new("http://example.com")?;
/// assert_eq!(vec![Quad::new(ex.clone(), ex.clone(), ex.clone(), None)], results);
/// # Result::Ok(())
/// # oxigraph::Result::Ok(())
/// ```
pub fn load_graph(
&mut self,
@ -992,8 +994,8 @@ impl<'a> MemoryTransaction<'a> {
///
/// Usage example:
/// ```
/// use oxigraph::{MemoryStore, DatasetSyntax};
/// use oxigraph::model::*;
/// use oxigraph::{MemoryStore, Result, DatasetSyntax};
///
/// let store = MemoryStore::new();
///
@ -1005,7 +1007,7 @@ impl<'a> MemoryTransaction<'a> {
/// let results: Vec<Quad> = store.quads_for_pattern(None, None, None, None).collect();
/// let ex = NamedNode::new("http://example.com")?;
/// assert_eq!(vec![Quad::new(ex.clone(), ex.clone(), ex.clone(), Some(ex.into()))], results);
/// # Result::Ok(())
/// # oxigraph::Result::Ok(())
/// ```
pub fn load_dataset(
&mut self,
@ -1102,9 +1104,9 @@ pub(crate) struct EncodedQuadsIter {
}
impl Iterator for EncodedQuadsIter {
type Item = Result<EncodedQuad, Error>;
type Item = Result<EncodedQuad, Infallible>;
fn next(&mut self) -> Option<Result<EncodedQuad, Error>> {
fn next(&mut self) -> Option<Result<EncodedQuad, Infallible>> {
self.iter.next().map(Ok)
}

@ -18,20 +18,24 @@ pub use crate::store::sled::SledStore;
use crate::model::*;
use crate::store::numeric_encoder::*;
use crate::{DatasetSyntax, Error, GraphSyntax, Result};
use crate::{DatasetSyntax, GraphSyntax};
use rio_api::formatter::{QuadsFormatter, TriplesFormatter};
use rio_api::parser::{QuadsParser, TriplesParser};
use rio_turtle::{
NQuadsFormatter, NQuadsParser, NTriplesFormatter, NTriplesParser, TriGFormatter, TriGParser,
TurtleFormatter, TurtleParser,
};
use rio_xml::{RdfXmlFormatter, RdfXmlParser};
use rio_xml::{RdfXmlError, RdfXmlFormatter, RdfXmlParser};
use std::collections::HashMap;
use std::error::Error;
use std::io;
use std::io::{BufRead, Write};
use std::iter::Iterator;
pub(crate) trait ReadableEncodedStore: StrLookup {
type QuadsIter: Iterator<Item = Result<EncodedQuad>> + 'static;
type Error: From<<Self as StrLookup>::Error> + Error + Into<io::Error> + 'static;
type QuadsIter: Iterator<Item = Result<EncodedQuad, <Self as ReadableEncodedStore>::Error>>
+ 'static;
fn encoded_quads_for_pattern(
&self,
@ -43,17 +47,17 @@ pub(crate) trait ReadableEncodedStore: StrLookup {
}
pub(crate) trait WritableEncodedStore: StrContainer {
type Error: From<<Self as StrContainer>::Error> + std::error::Error + Into<Error>;
type Error: From<<Self as StrContainer>::Error> + Error + Into<io::Error>;
fn insert_encoded(
&mut self,
quad: &EncodedQuad,
) -> std::result::Result<(), <Self as WritableEncodedStore>::Error>;
) -> Result<(), <Self as WritableEncodedStore>::Error>;
fn remove_encoded(
&mut self,
quad: &EncodedQuad,
) -> std::result::Result<(), <Self as WritableEncodedStore>::Error>;
) -> Result<(), <Self as WritableEncodedStore>::Error>;
}
fn load_graph<S: WritableEncodedStore>(
@ -62,7 +66,10 @@ fn load_graph<S: WritableEncodedStore>(
syntax: GraphSyntax,
to_graph_name: &GraphName,
base_iri: Option<&str>,
) -> Result<()> {
) -> Result<(), crate::Error>
where
crate::Error: From<<S as WritableEncodedStore>::Error> + From<<S as StrContainer>::Error>,
{
let base_iri = base_iri.unwrap_or("");
match syntax {
GraphSyntax::NTriples => {
@ -81,9 +88,11 @@ fn load_from_triple_parser<S: WritableEncodedStore, P: TriplesParser>(
store: &mut S,
mut parser: P,
to_graph_name: &GraphName,
) -> Result<()>
) -> Result<(), crate::Error>
where
Error: From<P::Error>,
crate::Error: From<P::Error>
+ From<<S as WritableEncodedStore>::Error>
+ From<<S as StrContainer>::Error>,
{
let mut bnode_map = HashMap::default();
let to_graph_name = store
@ -92,16 +101,17 @@ where
parser.parse_all(&mut move |t| {
let quad = store
.encode_rio_triple_in_graph(t, to_graph_name, &mut bnode_map)
.map_err(|e| e.into())?;
store.insert_encoded(&quad).map_err(|e| e.into())
.map_err(crate::Error::from)?;
store.insert_encoded(&quad).map_err(crate::Error::from)?;
Ok(())
})
}
fn dump_graph(
triples: impl Iterator<Item = Result<Triple>>,
triples: impl Iterator<Item = Result<Triple, io::Error>>,
writer: &mut impl Write,
syntax: GraphSyntax,
) -> Result<()> {
) -> Result<(), io::Error> {
match syntax {
GraphSyntax::NTriples => {
let mut formatter = NTriplesFormatter::new(writer);
@ -118,22 +128,29 @@ fn dump_graph(
formatter.finish()?;
}
GraphSyntax::RdfXml => {
let mut formatter = RdfXmlFormatter::new(writer)?;
let mut formatter = RdfXmlFormatter::new(writer).map_err(map_xml_err)?;
for triple in triples {
formatter.format(&(&triple?).into())?;
formatter.format(&(&triple?).into()).map_err(map_xml_err)?;
}
formatter.finish()?;
formatter.finish().map_err(map_xml_err)?;
}
}
Ok(())
}
fn map_xml_err(e: RdfXmlError) -> io::Error {
io::Error::new(io::ErrorKind::Other, e)
}
fn load_dataset<S: WritableEncodedStore>(
store: &mut S,
reader: impl BufRead,
syntax: DatasetSyntax,
base_iri: Option<&str>,
) -> Result<()> {
) -> Result<(), crate::Error>
where
crate::Error: From<<S as WritableEncodedStore>::Error> + From<<S as StrContainer>::Error>,
{
let base_iri = base_iri.unwrap_or("");
match syntax {
DatasetSyntax::NQuads => load_from_quad_parser(store, NQuadsParser::new(reader)?),
@ -144,24 +161,27 @@ fn load_dataset<S: WritableEncodedStore>(
fn load_from_quad_parser<S: WritableEncodedStore, P: QuadsParser>(
store: &mut S,
mut parser: P,
) -> Result<()>
) -> Result<(), crate::Error>
where
Error: From<P::Error>,
crate::Error: From<P::Error>
+ From<<S as WritableEncodedStore>::Error>
+ From<<S as StrContainer>::Error>,
{
let mut bnode_map = HashMap::default();
parser.parse_all(&mut move |q| {
let quad = store
.encode_rio_quad(q, &mut bnode_map)
.map_err(|e| e.into())?;
store.insert_encoded(&quad).map_err(|e| e.into())
.map_err(crate::Error::from)?;
store.insert_encoded(&quad).map_err(crate::Error::from)?;
Ok(())
})
}
fn dump_dataset(
quads: impl Iterator<Item = Result<Quad>>,
quads: impl Iterator<Item = Result<Quad, io::Error>>,
writer: &mut impl Write,
syntax: DatasetSyntax,
) -> Result<()> {
) -> Result<(), io::Error> {
match syntax {
DatasetSyntax::NQuads => {
let mut formatter = NQuadsFormatter::new(writer);

@ -1,22 +1,21 @@
#![allow(clippy::unreadable_literal)]
use crate::error::UnwrapInfallible;
use crate::error::{Infallible, UnwrapInfallible};
use crate::model::vocab::rdf;
use crate::model::vocab::xsd;
use crate::model::xsd::*;
use crate::model::*;
use crate::{Error as OxError, Result as OxResult};
use rand::random;
use rio_api::model as rio;
use siphasher::sip128::{Hasher128, SipHasher24};
use std::collections::HashMap;
use std::convert::Infallible;
use std::error::Error;
use std::hash::Hash;
use std::hash::Hasher;
use std::io::{Error as IoError, ErrorKind, Read, Result as IoResult};
use std::io;
use std::io::Read;
use std::mem::size_of;
use std::str;
use std::{fmt, str};
#[derive(Ord, PartialOrd, Eq, PartialEq, Debug, Copy, Clone, Hash)]
#[repr(transparent)]
@ -609,17 +608,17 @@ impl From<&Quad> for EncodedQuad {
}
pub trait TermReader {
fn read_term(&mut self) -> IoResult<EncodedTerm>;
fn read_spog_quad(&mut self) -> IoResult<EncodedQuad>;
fn read_posg_quad(&mut self) -> IoResult<EncodedQuad>;
fn read_ospg_quad(&mut self) -> IoResult<EncodedQuad>;
fn read_gspo_quad(&mut self) -> IoResult<EncodedQuad>;
fn read_gpos_quad(&mut self) -> IoResult<EncodedQuad>;
fn read_gosp_quad(&mut self) -> IoResult<EncodedQuad>;
fn read_term(&mut self) -> Result<EncodedTerm, io::Error>;
fn read_spog_quad(&mut self) -> Result<EncodedQuad, io::Error>;
fn read_posg_quad(&mut self) -> Result<EncodedQuad, io::Error>;
fn read_ospg_quad(&mut self) -> Result<EncodedQuad, io::Error>;
fn read_gspo_quad(&mut self) -> Result<EncodedQuad, io::Error>;
fn read_gpos_quad(&mut self) -> Result<EncodedQuad, io::Error>;
fn read_gosp_quad(&mut self) -> Result<EncodedQuad, io::Error>;
}
impl<R: Read> TermReader for R {
fn read_term(&mut self) -> IoResult<EncodedTerm> {
fn read_term(&mut self) -> Result<EncodedTerm, io::Error> {
let mut type_buffer = [0];
self.read_exact(&mut type_buffer)?;
match type_buffer[0] {
@ -732,14 +731,13 @@ impl<R: Read> TermReader for R {
DayTimeDuration::from_be_bytes(buffer),
))
}
_ => Err(IoError::new(
ErrorKind::InvalidData,
_ => Err(DecoderError::build(
"the term buffer has an invalid type id",
)),
}
}
fn read_spog_quad(&mut self) -> IoResult<EncodedQuad> {
fn read_spog_quad(&mut self) -> Result<EncodedQuad, io::Error> {
let subject = self.read_term()?;
let predicate = self.read_term()?;
let object = self.read_term()?;
@ -752,7 +750,7 @@ impl<R: Read> TermReader for R {
})
}
fn read_posg_quad(&mut self) -> IoResult<EncodedQuad> {
fn read_posg_quad(&mut self) -> Result<EncodedQuad, io::Error> {
let predicate = self.read_term()?;
let object = self.read_term()?;
let subject = self.read_term()?;
@ -765,7 +763,7 @@ impl<R: Read> TermReader for R {
})
}
fn read_ospg_quad(&mut self) -> IoResult<EncodedQuad> {
fn read_ospg_quad(&mut self) -> Result<EncodedQuad, io::Error> {
let object = self.read_term()?;
let subject = self.read_term()?;
let predicate = self.read_term()?;
@ -778,7 +776,7 @@ impl<R: Read> TermReader for R {
})
}
fn read_gspo_quad(&mut self) -> IoResult<EncodedQuad> {
fn read_gspo_quad(&mut self) -> Result<EncodedQuad, io::Error> {
let graph_name = self.read_term()?;
let subject = self.read_term()?;
let predicate = self.read_term()?;
@ -791,7 +789,7 @@ impl<R: Read> TermReader for R {
})
}
fn read_gpos_quad(&mut self) -> IoResult<EncodedQuad> {
fn read_gpos_quad(&mut self) -> Result<EncodedQuad, io::Error> {
let graph_name = self.read_term()?;
let predicate = self.read_term()?;
let object = self.read_term()?;
@ -804,7 +802,7 @@ impl<R: Read> TermReader for R {
})
}
fn read_gosp_quad(&mut self) -> IoResult<EncodedQuad> {
fn read_gosp_quad(&mut self) -> Result<EncodedQuad, io::Error> {
let graph_name = self.read_term()?;
let object = self.read_term()?;
let subject = self.read_term()?;
@ -858,14 +856,14 @@ pub fn write_term(sink: &mut Vec<u8>, term: EncodedTerm) {
}
}
pub trait StrLookup {
type Error: Error + Into<OxError>;
pub(crate) trait StrLookup {
type Error: Error + Into<io::Error>;
fn get_str(&self, id: StrHash) -> Result<Option<String>, Self::Error>;
}
pub trait StrContainer {
type Error: Error + Into<OxError>;
pub(crate) trait StrContainer {
type Error: Error + Into<io::Error>;
fn insert_str(&mut self, key: StrHash, value: &str) -> Result<(), Self::Error>;
@ -924,8 +922,8 @@ impl StrContainer for MemoryStrStore {
}
}
pub trait Encoder {
type Error: Error + Into<OxError>;
pub(crate) trait Encoder {
type Error: Error + Into<io::Error>;
fn encode_named_node(&mut self, named_node: &NamedNode) -> Result<EncodedTerm, Self::Error> {
self.encode_rio_named_node(named_node.into())
@ -1221,32 +1219,35 @@ pub fn parse_day_time_duration_str(value: &str) -> Option<EncodedTerm> {
value.parse().map(EncodedTerm::DayTimeDurationLiteral).ok()
}
pub trait Decoder {
fn decode_term(&self, encoded: EncodedTerm) -> OxResult<Term>;
pub(crate) trait Decoder {
fn decode_term(&self, encoded: EncodedTerm) -> Result<Term, io::Error>;
fn decode_named_or_blank_node(&self, encoded: EncodedTerm) -> OxResult<NamedOrBlankNode> {
fn decode_named_or_blank_node(
&self,
encoded: EncodedTerm,
) -> Result<NamedOrBlankNode, io::Error> {
match self.decode_term(encoded)? {
Term::NamedNode(named_node) => Ok(named_node.into()),
Term::BlankNode(blank_node) => Ok(blank_node.into()),
Term::Literal(_) => Err(OxError::msg(
Term::Literal(_) => Err(DecoderError::build(
"A literal has ben found instead of a named node",
)),
}
}
fn decode_named_node(&self, encoded: EncodedTerm) -> OxResult<NamedNode> {
fn decode_named_node(&self, encoded: EncodedTerm) -> Result<NamedNode, io::Error> {
match self.decode_term(encoded)? {
Term::NamedNode(named_node) => Ok(named_node),
Term::BlankNode(_) => Err(OxError::msg(
Term::BlankNode(_) => Err(DecoderError::build(
"A blank node has been found instead of a named node",
)),
Term::Literal(_) => Err(OxError::msg(
Term::Literal(_) => Err(DecoderError::build(
"A literal has ben found instead of a named node",
)),
}
}
fn decode_triple(&self, encoded: &EncodedQuad) -> OxResult<Triple> {
fn decode_triple(&self, encoded: &EncodedQuad) -> Result<Triple, io::Error> {
Ok(Triple::new(
self.decode_named_or_blank_node(encoded.subject)?,
self.decode_named_node(encoded.predicate)?,
@ -1254,7 +1255,7 @@ pub trait Decoder {
))
}
fn decode_quad(&self, encoded: &EncodedQuad) -> OxResult<Quad> {
fn decode_quad(&self, encoded: &EncodedQuad) -> Result<Quad, io::Error> {
Ok(Quad::new(
self.decode_named_or_blank_node(encoded.subject)?,
self.decode_named_node(encoded.predicate)?,
@ -1268,11 +1269,11 @@ pub trait Decoder {
}
impl<S: StrLookup> Decoder for S {
fn decode_term(&self, encoded: EncodedTerm) -> OxResult<Term> {
fn decode_term(&self, encoded: EncodedTerm) -> Result<Term, io::Error> {
match encoded {
EncodedTerm::DefaultGraph => {
Err(OxError::msg("The default graph tag is not a valid term"))
}
EncodedTerm::DefaultGraph => Err(DecoderError::build(
"The default graph tag is not a valid term",
)),
EncodedTerm::NamedNode { iri_id } => {
Ok(NamedNode::new_unchecked(get_required_str(self, iri_id)?).into())
}
@ -1314,15 +1315,34 @@ impl<S: StrLookup> Decoder for S {
}
}
fn get_required_str(lookup: &impl StrLookup, id: StrHash) -> OxResult<String> {
fn get_required_str(lookup: &impl StrLookup, id: StrHash) -> Result<String, io::Error> {
lookup.get_str(id).map_err(|e| e.into())?.ok_or_else(|| {
OxError::msg(format!(
DecoderError::build(format!(
"Not able to find the string with id {:?} in the string store",
id
))
})
}
#[derive(Debug)]
pub struct DecoderError {
msg: String,
}
impl DecoderError {
pub fn build(msg: impl Into<String>) -> io::Error {
io::Error::new(io::ErrorKind::InvalidData, Self { msg: msg.into() })
}
}
impl fmt::Display for DecoderError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.msg)
}
}
impl Error for DecoderError {}
#[test]
fn test_encoding() {
let mut store = MemoryStrStore::default();

@ -1,15 +1,16 @@
//! Store based on the [RocksDB](https://rocksdb.org/) key-value database.
use crate::error::UnwrapInfallible;
use crate::error::{Infallible, UnwrapInfallible};
use crate::model::*;
use crate::sparql::{Query, QueryOptions, QueryResult, SimplePreparedQuery};
use crate::store::numeric_encoder::*;
use crate::store::{
dump_dataset, dump_graph, load_dataset, load_graph, ReadableEncodedStore, WritableEncodedStore,
};
use crate::{DatasetSyntax, GraphSyntax, Result};
use crate::{DatasetSyntax, GraphSyntax};
use rocksdb::*;
use std::convert::{Infallible, TryInto};
use std::convert::TryInto;
use std::io;
use std::io::{BufRead, Cursor, Write};
use std::mem::{take, transmute};
use std::path::Path;
@ -23,8 +24,8 @@ use std::{fmt, str};
///
/// Usage example:
/// ```
/// use oxigraph::RocksDbStore;
/// use oxigraph::model::*;
/// use oxigraph::{Result, RocksDbStore};
/// use oxigraph::sparql::{QueryOptions, QueryResult};
/// # use std::fs::remove_dir_all;
///
@ -37,7 +38,7 @@ use std::{fmt, str};
/// store.insert(&quad)?;
///
/// // quad filter
/// let results: Result<Vec<Quad>> = store.quads_for_pattern(None, None, None, None).collect();
/// let results: Result<Vec<Quad>,_> = store.quads_for_pattern(None, None, None, None).collect();
/// assert_eq!(vec![quad], results?);
///
/// // SPARQL query
@ -47,7 +48,7 @@ use std::{fmt, str};
/// #
/// # };
/// # remove_dir_all("example.db")?;
/// # Result::Ok(())
/// # oxigraph::Result::Ok(())
/// ```
#[derive(Clone)]
pub struct RocksDbStore {
@ -72,14 +73,14 @@ const MAX_TRANSACTION_SIZE: usize = 1024;
impl RocksDbStore {
/// Opens a `RocksDbStore`
pub fn open(path: impl AsRef<Path>) -> Result<Self> {
pub fn open(path: impl AsRef<Path>) -> Result<Self, io::Error> {
let mut options = Options::default();
options.create_if_missing(true);
options.create_missing_column_families(true);
options.set_compaction_style(DBCompactionStyle::Universal);
let new = Self {
db: Arc::new(DB::open_cf(&options, path, &COLUMN_FAMILIES)?),
db: Arc::new(DB::open_cf(&options, path, &COLUMN_FAMILIES).map_err(map_err)?),
};
let mut transaction = new.auto_batch_writer();
@ -96,7 +97,7 @@ impl RocksDbStore {
&self,
query: impl TryInto<Query, Error = impl Into<crate::Error>>,
options: QueryOptions,
) -> Result<QueryResult> {
) -> Result<QueryResult, crate::Error> {
self.prepare_query(query, options)?.exec()
}
@ -108,7 +109,7 @@ impl RocksDbStore {
&self,
query: impl TryInto<Query, Error = impl Into<crate::Error>>,
options: QueryOptions,
) -> Result<RocksDbPreparedQuery> {
) -> Result<RocksDbPreparedQuery, crate::Error> {
Ok(RocksDbPreparedQuery(SimplePreparedQuery::new(
(*self).clone(),
query,
@ -125,7 +126,7 @@ impl RocksDbStore {
predicate: Option<&NamedNode>,
object: Option<&Term>,
graph_name: Option<&GraphName>,
) -> impl Iterator<Item = Result<Quad>> {
) -> impl Iterator<Item = Result<Quad, io::Error>> {
let subject = subject.map(|s| s.into());
let predicate = predicate.map(|p| p.into());
let object = object.map(|o| o.into());
@ -136,7 +137,7 @@ impl RocksDbStore {
}
/// Checks if this store contains a given quad
pub fn contains(&self, quad: &Quad) -> Result<bool> {
pub fn contains(&self, quad: &Quad) -> Result<bool, io::Error> {
let quad = quad.into();
self.contains_encoded(&quad)
}
@ -162,10 +163,10 @@ impl RocksDbStore {
/// Nothing is done if the closure returns `Err`.
///
/// See `MemoryStore` for a usage example.
pub fn transaction<'a>(
pub fn transaction<'a, E: From<io::Error>>(
&'a self,
f: impl FnOnce(&mut RocksDbTransaction<'a>) -> Result<()>,
) -> Result<()> {
f: impl FnOnce(&mut RocksDbTransaction<'a>) -> Result<(), E>,
) -> Result<(), E> {
let mut transaction = RocksDbTransaction {
inner: BatchWriter {
store: self,
@ -174,7 +175,7 @@ impl RocksDbStore {
},
};
f(&mut transaction)?;
transaction.inner.apply()
Ok(transaction.inner.apply()?)
}
/// Loads a graph file (i.e. triples) into the store
@ -189,10 +190,10 @@ impl RocksDbStore {
syntax: GraphSyntax,
to_graph_name: &GraphName,
base_iri: Option<&str>,
) -> Result<()> {
) -> Result<(), crate::Error> {
let mut transaction = self.auto_batch_writer();
load_graph(&mut transaction, reader, syntax, to_graph_name, base_iri)?;
transaction.apply()
Ok(transaction.apply()?)
}
/// Loads a dataset file (i.e. quads) into the store.
@ -206,14 +207,14 @@ impl RocksDbStore {
reader: impl BufRead,
syntax: DatasetSyntax,
base_iri: Option<&str>,
) -> Result<()> {
) -> Result<(), crate::Error> {
let mut transaction = self.auto_batch_writer();
load_dataset(&mut transaction, reader, syntax, base_iri)?;
transaction.apply()
Ok(transaction.apply()?)
}
/// Adds a quad to this store.
pub fn insert(&self, quad: &Quad) -> Result<()> {
pub fn insert(&self, quad: &Quad) -> Result<(), io::Error> {
let mut transaction = self.auto_batch_writer();
let quad = transaction.encode_quad(quad)?;
transaction.insert_encoded(&quad)?;
@ -221,7 +222,7 @@ impl RocksDbStore {
}
/// Removes a quad from this store.
pub fn remove(&self, quad: &Quad) -> Result<()> {
pub fn remove(&self, quad: &Quad) -> Result<(), io::Error> {
let mut transaction = self.auto_batch_writer();
let quad = quad.into();
transaction.remove_encoded(&quad)?;
@ -236,7 +237,7 @@ impl RocksDbStore {
writer: &mut impl Write,
syntax: GraphSyntax,
from_graph_name: &GraphName,
) -> Result<()> {
) -> Result<(), io::Error> {
dump_graph(
self.quads_for_pattern(None, None, None, Some(from_graph_name))
.map(|q| Ok(q?.into())),
@ -248,7 +249,11 @@ impl RocksDbStore {
/// Dumps the store dataset into a file.
///
/// See `MemoryStore` for a usage example.
pub fn dump_dataset(&self, writer: &mut impl Write, syntax: DatasetSyntax) -> Result<()> {
pub fn dump_dataset(
&self,
writer: &mut impl Write,
syntax: DatasetSyntax,
) -> Result<(), io::Error> {
dump_dataset(
self.quads_for_pattern(None, None, None, None),
writer,
@ -294,10 +299,14 @@ impl RocksDbStore {
}
}
fn contains_encoded(&self, quad: &EncodedQuad) -> Result<bool> {
fn contains_encoded(&self, quad: &EncodedQuad) -> Result<bool, io::Error> {
let mut buffer = Vec::with_capacity(4 * WRITTEN_TERM_MAX_SIZE);
write_spog_quad(&mut buffer, quad);
Ok(self.db.get_pinned_cf(self.spog_cf(), &buffer)?.is_some())
Ok(self
.db
.get_pinned_cf(self.spog_cf(), &buffer)
.map_err(map_err)?
.is_some())
}
fn quads(&self) -> DecodingIndexIterator {
@ -455,18 +464,20 @@ impl fmt::Display for RocksDbStore {
}
impl StrLookup for RocksDbStore {
type Error = crate::Error;
type Error = io::Error;
fn get_str(&self, id: StrHash) -> Result<Option<String>> {
Ok(self
.db
.get_cf(self.id2str_cf(), &id.to_be_bytes())?
fn get_str(&self, id: StrHash) -> Result<Option<String>, io::Error> {
self.db
.get_cf(self.id2str_cf(), &id.to_be_bytes())
.map_err(map_err)?
.map(String::from_utf8)
.transpose()?)
.transpose()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
}
}
impl ReadableEncodedStore for RocksDbStore {
type Error = io::Error;
type QuadsIter = DecodingIndexIterator;
fn encoded_quads_for_pattern(
@ -538,7 +549,7 @@ pub struct RocksDbPreparedQuery(SimplePreparedQuery<RocksDbStore>);
impl RocksDbPreparedQuery {
/// Evaluates the query and returns its results
pub fn exec(&self) -> Result<QueryResult> {
pub fn exec(&self) -> Result<QueryResult, crate::Error> {
self.0.exec()
}
}
@ -562,7 +573,7 @@ impl RocksDbTransaction<'_> {
syntax: GraphSyntax,
to_graph_name: &GraphName,
base_iri: Option<&str>,
) -> Result<()> {
) -> Result<(), crate::Error> {
load_graph(&mut self.inner, reader, syntax, to_graph_name, base_iri)
}
@ -578,7 +589,7 @@ impl RocksDbTransaction<'_> {
reader: impl BufRead,
syntax: DatasetSyntax,
base_iri: Option<&str>,
) -> Result<()> {
) -> Result<(), crate::Error> {
load_dataset(&mut self.inner, reader, syntax, base_iri)
}
@ -604,7 +615,7 @@ struct BatchWriter<'a> {
impl StrContainer for BatchWriter<'_> {
type Error = Infallible;
fn insert_str(&mut self, key: StrHash, value: &str) -> std::result::Result<(), Infallible> {
fn insert_str(&mut self, key: StrHash, value: &str) -> Result<(), Infallible> {
self.batch
.put_cf(self.store.id2str_cf(), &key.to_be_bytes(), value);
Ok(())
@ -614,7 +625,7 @@ impl StrContainer for BatchWriter<'_> {
impl WritableEncodedStore for BatchWriter<'_> {
type Error = Infallible;
fn insert_encoded(&mut self, quad: &EncodedQuad) -> std::result::Result<(), Infallible> {
fn insert_encoded(&mut self, quad: &EncodedQuad) -> Result<(), Infallible> {
write_spog_quad(&mut self.buffer, quad);
self.batch.put_cf(self.store.spog_cf(), &self.buffer, &[]);
self.buffer.clear();
@ -642,7 +653,7 @@ impl WritableEncodedStore for BatchWriter<'_> {
Ok(())
}
fn remove_encoded(&mut self, quad: &EncodedQuad) -> std::result::Result<(), Infallible> {
fn remove_encoded(&mut self, quad: &EncodedQuad) -> Result<(), Infallible> {
write_spog_quad(&mut self.buffer, quad);
self.batch.delete_cf(self.store.spog_cf(), &self.buffer);
self.buffer.clear();
@ -672,8 +683,8 @@ impl WritableEncodedStore for BatchWriter<'_> {
}
impl BatchWriter<'_> {
fn apply(self) -> Result<()> {
Ok(self.store.db.write(self.batch)?)
fn apply(self) -> Result<(), io::Error> {
self.store.db.write(self.batch).map_err(map_err)
}
}
@ -682,35 +693,39 @@ struct AutoBatchWriter<'a> {
}
impl StrContainer for AutoBatchWriter<'_> {
type Error = crate::Error;
type Error = io::Error;
fn insert_str(&mut self, key: StrHash, value: &str) -> Result<()> {
fn insert_str(&mut self, key: StrHash, value: &str) -> Result<(), io::Error> {
Ok(self.inner.insert_str(key, value)?)
}
}
impl WritableEncodedStore for AutoBatchWriter<'_> {
type Error = crate::Error;
type Error = io::Error;
fn insert_encoded(&mut self, quad: &EncodedQuad) -> Result<()> {
fn insert_encoded(&mut self, quad: &EncodedQuad) -> Result<(), io::Error> {
self.inner.insert_encoded(quad)?;
self.apply_if_big()
}
fn remove_encoded(&mut self, quad: &EncodedQuad) -> Result<()> {
fn remove_encoded(&mut self, quad: &EncodedQuad) -> Result<(), io::Error> {
self.inner.remove_encoded(quad)?;
self.apply_if_big()
}
}
impl AutoBatchWriter<'_> {
fn apply(self) -> Result<()> {
fn apply(self) -> Result<(), io::Error> {
self.inner.apply()
}
fn apply_if_big(&mut self) -> Result<()> {
fn apply_if_big(&mut self) -> Result<(), io::Error> {
if self.inner.batch.len() > MAX_TRANSACTION_SIZE {
self.inner.store.db.write(take(&mut self.inner.batch))?;
self.inner
.store
.db
.write(take(&mut self.inner.batch))
.map_err(map_err)?;
}
Ok(())
}
@ -779,12 +794,12 @@ pub(crate) struct DecodingIndexIterator {
}
impl Iterator for DecodingIndexIterator {
type Item = Result<EncodedQuad>;
type Item = Result<EncodedQuad, io::Error>;
fn next(&mut self) -> Option<Result<EncodedQuad>> {
fn next(&mut self) -> Option<Result<EncodedQuad, io::Error>> {
if let Some(key) = self.iter.iter.key() {
if key.starts_with(&self.prefix) {
let result = self.encoding.decode(key).map_err(crate::Error::from);
let result = self.encoding.decode(key);
self.iter.iter.next();
Some(result)
} else {
@ -849,23 +864,26 @@ enum QuadEncoding {
}
impl QuadEncoding {
fn decode(self, buffer: &[u8]) -> Result<EncodedQuad> {
fn decode(self, buffer: &[u8]) -> Result<EncodedQuad, io::Error> {
let mut cursor = Cursor::new(&buffer);
Ok(match self {
match self {
QuadEncoding::SPOG => cursor.read_spog_quad(),
QuadEncoding::POSG => cursor.read_posg_quad(),
QuadEncoding::OSPG => cursor.read_ospg_quad(),
QuadEncoding::GSPO => cursor.read_gspo_quad(),
QuadEncoding::GPOS => cursor.read_gpos_quad(),
QuadEncoding::GOSP => cursor.read_gosp_quad(),
}?)
}
}
}
fn map_err(e: Error) -> io::Error {
io::Error::new(io::ErrorKind::Other, e)
}
#[test]
fn store() -> Result<()> {
fn store() -> Result<(), crate::Error> {
use crate::model::*;
use crate::*;
use rand::random;
use std::env::temp_dir;
use std::fs::remove_dir_all;
@ -895,25 +913,25 @@ fn store() -> Result<()> {
assert_eq!(
store
.quads_for_pattern(None, None, None, None)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
all_o
);
assert_eq!(
store
.quads_for_pattern(Some(&main_s), None, None, None)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
all_o
);
assert_eq!(
store
.quads_for_pattern(Some(&main_s), Some(&main_p), None, None)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
all_o
);
assert_eq!(
store
.quads_for_pattern(Some(&main_s), Some(&main_p), Some(&main_o), None)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
target
);
assert_eq!(
@ -924,7 +942,7 @@ fn store() -> Result<()> {
Some(&main_o),
Some(&GraphName::DefaultGraph)
)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
target
);
assert_eq!(
@ -935,13 +953,13 @@ fn store() -> Result<()> {
None,
Some(&GraphName::DefaultGraph)
)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
all_o
);
assert_eq!(
store
.quads_for_pattern(Some(&main_s), None, Some(&main_o), None)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
target
);
assert_eq!(
@ -952,37 +970,37 @@ fn store() -> Result<()> {
Some(&main_o),
Some(&GraphName::DefaultGraph)
)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
target
);
assert_eq!(
store
.quads_for_pattern(Some(&main_s), None, None, Some(&GraphName::DefaultGraph))
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
all_o
);
assert_eq!(
store
.quads_for_pattern(None, Some(&main_p), None, None)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
all_o
);
assert_eq!(
store
.quads_for_pattern(None, Some(&main_p), Some(&main_o), None)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
target
);
assert_eq!(
store
.quads_for_pattern(None, None, Some(&main_o), None)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
target
);
assert_eq!(
store
.quads_for_pattern(None, None, None, Some(&GraphName::DefaultGraph))
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
all_o
);
assert_eq!(
@ -993,7 +1011,7 @@ fn store() -> Result<()> {
Some(&main_o),
Some(&GraphName::DefaultGraph)
)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
target
);
}

@ -1,18 +1,18 @@
//! Store based on the [Sled](https://sled.rs/) key-value database.
use crate::error::UnwrapInfallible;
use crate::error::{Infallible, UnwrapInfallible};
use crate::model::*;
use crate::sparql::{Query, QueryOptions, QueryResult, SimplePreparedQuery};
use crate::store::numeric_encoder::*;
use crate::store::{
dump_dataset, dump_graph, load_dataset, load_graph, ReadableEncodedStore, WritableEncodedStore,
};
use crate::{DatasetSyntax, Error, GraphSyntax, Result};
use crate::{DatasetSyntax, GraphSyntax};
use sled::{Batch, Config, Iter, Tree};
use std::convert::{Infallible, TryInto};
use std::convert::TryInto;
use std::io::{BufRead, Cursor, Write};
use std::path::Path;
use std::{fmt, str};
use std::{fmt, io, str};
/// Store based on the [Sled](https://sled.rs/) key-value database.
/// It encodes a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) and allows to query and update it using SPARQL.
@ -23,9 +23,9 @@ use std::{fmt, str};
///
/// Usage example:
/// ```
/// use oxigraph::model::*;
/// use oxigraph::{Result, SledStore};
/// use oxigraph::SledStore;
/// use oxigraph::sparql::{QueryOptions, QueryResult};
/// use oxigraph::model::*;
/// # use std::fs::remove_dir_all;
///
/// # {
@ -37,7 +37,7 @@ use std::{fmt, str};
/// store.insert(&quad)?;
///
/// // quad filter
/// let results: Result<Vec<Quad>> = store.quads_for_pattern(None, None, None, None).collect();
/// let results: Result<Vec<Quad>,_> = store.quads_for_pattern(None, None, None, None).collect();
/// assert_eq!(vec![quad], results?);
///
/// // SPARQL query
@ -47,7 +47,7 @@ use std::{fmt, str};
/// #
/// # };
/// # remove_dir_all("example.db")?;
/// # Result::Ok(())
/// # oxigraph::Result::Ok(())
/// ```
#[derive(Clone)]
pub struct SledStore {
@ -66,16 +66,16 @@ const GOSP_PREFIX: u8 = 6;
impl SledStore {
/// Opens a temporary `SledStore` that will be deleted after drop.
pub fn new() -> Result<Self> {
pub fn new() -> Result<Self, io::Error> {
Self::do_open(&Config::new().temporary(true))
}
/// Opens a `SledStore`
pub fn open(path: impl AsRef<Path>) -> Result<Self> {
pub fn open(path: impl AsRef<Path>) -> Result<Self, io::Error> {
Self::do_open(&Config::new().path(path))
}
fn do_open(config: &Config) -> Result<Self> {
fn do_open(config: &Config) -> Result<Self, io::Error> {
let db = config.open()?;
let new = Self {
id2str: db.open_tree("id2str")?,
@ -90,9 +90,9 @@ impl SledStore {
/// See `MemoryStore` for a usage example.
pub fn query(
&self,
query: impl TryInto<Query, Error = impl Into<Error>>,
query: impl TryInto<Query, Error = impl Into<crate::Error>>,
options: QueryOptions,
) -> Result<QueryResult> {
) -> Result<QueryResult, crate::Error> {
self.prepare_query(query, options)?.exec()
}
@ -101,9 +101,9 @@ impl SledStore {
/// See `MemoryStore` for a usage example.
pub fn prepare_query(
&self,
query: impl TryInto<Query, Error = impl Into<Error>>,
query: impl TryInto<Query, Error = impl Into<crate::Error>>,
options: QueryOptions,
) -> Result<SledPreparedQuery> {
) -> Result<SledPreparedQuery, crate::Error> {
Ok(SledPreparedQuery(SimplePreparedQuery::new(
(*self).clone(),
query,
@ -120,7 +120,7 @@ impl SledStore {
predicate: Option<&NamedNode>,
object: Option<&Term>,
graph_name: Option<&GraphName>,
) -> impl Iterator<Item = Result<Quad>> {
) -> impl Iterator<Item = Result<Quad, io::Error>> {
let subject = subject.map(|s| s.into());
let predicate = predicate.map(|p| p.into());
let object = object.map(|o| o.into());
@ -131,7 +131,7 @@ impl SledStore {
}
/// Checks if this store contains a given quad
pub fn contains(&self, quad: &Quad) -> Result<bool> {
pub fn contains(&self, quad: &Quad) -> Result<bool, io::Error> {
let quad = quad.into();
self.contains_encoded(&quad)
}
@ -152,15 +152,15 @@ impl SledStore {
/// Nothing is done if the closure returns `Err`.
///
/// See `MemoryStore` for a usage example.
pub fn transaction<'a>(
pub fn transaction<'a, E: From<io::Error>>(
&'a self,
f: impl FnOnce(&mut SledTransaction<'a>) -> Result<()>,
) -> Result<()> {
f: impl FnOnce(&mut SledTransaction<'a>) -> Result<(), E>,
) -> Result<(), E> {
let mut transaction = SledTransaction {
inner: BatchWriter::new(self),
};
f(&mut transaction)?;
transaction.inner.apply()
Ok(transaction.inner.apply()?)
}
/// Loads a graph file (i.e. triples) into the store
@ -175,7 +175,7 @@ impl SledStore {
syntax: GraphSyntax,
to_graph_name: &GraphName,
base_iri: Option<&str>,
) -> Result<()> {
) -> Result<(), crate::Error> {
load_graph(
&mut DirectWriter::new(self),
reader,
@ -196,19 +196,19 @@ impl SledStore {
reader: impl BufRead,
syntax: DatasetSyntax,
base_iri: Option<&str>,
) -> Result<()> {
) -> Result<(), crate::Error> {
load_dataset(&mut DirectWriter::new(self), reader, syntax, base_iri)
}
/// Adds a quad to this store.
pub fn insert(&self, quad: &Quad) -> Result<()> {
pub fn insert(&self, quad: &Quad) -> Result<(), io::Error> {
let mut writer = DirectWriter::new(self);
let quad = writer.encode_quad(quad)?;
writer.insert_encoded(&quad)
}
/// Removes a quad from this store.
pub fn remove(&self, quad: &Quad) -> Result<()> {
pub fn remove(&self, quad: &Quad) -> Result<(), io::Error> {
let quad = quad.into();
DirectWriter::new(self).remove_encoded(&quad)
}
@ -221,7 +221,7 @@ impl SledStore {
writer: &mut impl Write,
syntax: GraphSyntax,
from_graph_name: &GraphName,
) -> Result<()> {
) -> Result<(), io::Error> {
dump_graph(
self.quads_for_pattern(None, None, None, Some(from_graph_name))
.map(|q| Ok(q?.into())),
@ -233,7 +233,11 @@ impl SledStore {
/// Dumps the store dataset into a file.
///
/// See `MemoryStore` for a usage example.
pub fn dump_dataset(&self, writer: &mut impl Write, syntax: DatasetSyntax) -> Result<()> {
pub fn dump_dataset(
&self,
writer: &mut impl Write,
syntax: DatasetSyntax,
) -> Result<(), io::Error> {
dump_dataset(
self.quads_for_pattern(None, None, None, None),
writer,
@ -241,7 +245,7 @@ impl SledStore {
)
}
fn contains_encoded(&self, quad: &EncodedQuad) -> Result<bool> {
fn contains_encoded(&self, quad: &EncodedQuad) -> Result<bool, io::Error> {
let mut buffer = Vec::with_capacity(4 * WRITTEN_TERM_MAX_SIZE);
write_spog_quad(&mut buffer, quad);
Ok(self.quads.contains_key(buffer)?)
@ -378,18 +382,19 @@ impl fmt::Display for SledStore {
}
impl StrLookup for SledStore {
type Error = Error;
type Error = io::Error;
fn get_str(&self, id: StrHash) -> Result<Option<String>> {
Ok(self
.id2str
fn get_str(&self, id: StrHash) -> Result<Option<String>, io::Error> {
self.id2str
.get(id.to_be_bytes())?
.map(|v| String::from_utf8(v.to_vec()))
.transpose()?)
.transpose()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
}
}
impl ReadableEncodedStore for SledStore {
type Error = io::Error;
type QuadsIter = DecodingQuadIterator;
fn encoded_quads_for_pattern(
@ -475,9 +480,9 @@ impl<'a> DirectWriter<'a> {
}
impl<'a> StrContainer for DirectWriter<'a> {
type Error = Error;
type Error = io::Error;
fn insert_str(&mut self, key: StrHash, value: &str) -> Result<()> {
fn insert_str(&mut self, key: StrHash, value: &str) -> Result<(), io::Error> {
self.store
.id2str
.insert(key.to_be_bytes().as_ref(), value)?;
@ -486,9 +491,9 @@ impl<'a> StrContainer for DirectWriter<'a> {
}
impl<'a> WritableEncodedStore for DirectWriter<'a> {
type Error = Error;
type Error = io::Error;
fn insert_encoded(&mut self, quad: &EncodedQuad) -> Result<()> {
fn insert_encoded(&mut self, quad: &EncodedQuad) -> Result<(), io::Error> {
write_spog_quad(&mut self.buffer, quad);
self.store.quads.insert(self.buffer.as_slice(), &[])?;
self.buffer.clear();
@ -516,7 +521,7 @@ impl<'a> WritableEncodedStore for DirectWriter<'a> {
Ok(())
}
fn remove_encoded(&mut self, quad: &EncodedQuad) -> Result<()> {
fn remove_encoded(&mut self, quad: &EncodedQuad) -> Result<(), io::Error> {
write_spog_quad(&mut self.buffer, quad);
self.store.quads.remove(self.buffer.as_slice())?;
self.buffer.clear();
@ -564,7 +569,7 @@ impl<'a> BatchWriter<'a> {
}
impl<'a> BatchWriter<'a> {
fn apply(self) -> Result<()> {
fn apply(self) -> Result<(), io::Error> {
self.store.id2str.apply_batch(self.id2str)?;
self.store.quads.apply_batch(self.quads)?;
Ok(())
@ -574,7 +579,7 @@ impl<'a> BatchWriter<'a> {
impl<'a> StrContainer for BatchWriter<'a> {
type Error = Infallible;
fn insert_str(&mut self, key: StrHash, value: &str) -> std::result::Result<(), Infallible> {
fn insert_str(&mut self, key: StrHash, value: &str) -> Result<(), Infallible> {
self.id2str.insert(key.to_be_bytes().as_ref(), value);
Ok(())
}
@ -583,7 +588,7 @@ impl<'a> StrContainer for BatchWriter<'a> {
impl<'a> WritableEncodedStore for BatchWriter<'a> {
type Error = Infallible;
fn insert_encoded(&mut self, quad: &EncodedQuad) -> std::result::Result<(), Infallible> {
fn insert_encoded(&mut self, quad: &EncodedQuad) -> Result<(), Infallible> {
write_spog_quad(&mut self.buffer, quad);
self.quads.insert(self.buffer.as_slice(), &[]);
self.buffer.clear();
@ -611,7 +616,7 @@ impl<'a> WritableEncodedStore for BatchWriter<'a> {
Ok(())
}
fn remove_encoded(&mut self, quad: &EncodedQuad) -> std::result::Result<(), Infallible> {
fn remove_encoded(&mut self, quad: &EncodedQuad) -> Result<(), Infallible> {
write_spog_quad(&mut self.buffer, quad);
self.quads.remove(self.buffer.as_slice());
self.buffer.clear();
@ -659,7 +664,7 @@ impl SledTransaction<'_> {
syntax: GraphSyntax,
to_graph_name: &GraphName,
base_iri: Option<&str>,
) -> Result<()> {
) -> Result<(), crate::Error> {
load_graph(&mut self.inner, reader, syntax, to_graph_name, base_iri)
}
@ -675,7 +680,7 @@ impl SledTransaction<'_> {
reader: impl BufRead,
syntax: DatasetSyntax,
base_iri: Option<&str>,
) -> Result<()> {
) -> Result<(), crate::Error> {
load_dataset(&mut self.inner, reader, syntax, base_iri)
}
@ -697,7 +702,7 @@ pub struct SledPreparedQuery(SimplePreparedQuery<SledStore>);
impl SledPreparedQuery {
/// Evaluates the query and returns its results
pub fn exec(&self) -> Result<QueryResult> {
pub fn exec(&self) -> Result<QueryResult, crate::Error> {
self.0.exec()
}
}
@ -747,9 +752,9 @@ pub(crate) struct DecodingQuadIterator {
}
impl Iterator for DecodingQuadIterator {
type Item = Result<EncodedQuad>;
type Item = Result<EncodedQuad, io::Error>;
fn next(&mut self) -> Option<Result<EncodedQuad>> {
fn next(&mut self) -> Option<Result<EncodedQuad, io::Error>> {
Some(match self.iter.next()? {
Ok((encoded, _)) => decode_quad(&encoded),
Err(error) => Err(error.into()),
@ -805,7 +810,7 @@ fn write_gosp_quad(sink: &mut Vec<u8>, quad: &EncodedQuad) {
write_term(sink, quad.predicate);
}
fn decode_quad(encoded: &[u8]) -> Result<EncodedQuad> {
fn decode_quad(encoded: &[u8]) -> Result<EncodedQuad, io::Error> {
let mut cursor = Cursor::new(&encoded[1..]);
match encoded[0] {
SPOG_PREFIX => Ok(cursor.read_spog_quad()?),
@ -814,14 +819,16 @@ fn decode_quad(encoded: &[u8]) -> Result<EncodedQuad> {
GSPO_PREFIX => Ok(cursor.read_gspo_quad()?),
GPOS_PREFIX => Ok(cursor.read_gpos_quad()?),
GOSP_PREFIX => Ok(cursor.read_gosp_quad()?),
_ => Err(Error::msg("Invalid quad type identifier")),
_ => Err(DecoderError::build(format!(
"Invalid quad type identifier: {}",
encoded[0]
))),
}
}
#[test]
fn store() -> Result<()> {
fn store() -> Result<(), crate::Error> {
use crate::model::*;
use crate::*;
let main_s = NamedOrBlankNode::from(BlankNode::default());
let main_p = NamedNode::new("http://example.com")?;
@ -844,25 +851,25 @@ fn store() -> Result<()> {
assert_eq!(
store
.quads_for_pattern(None, None, None, None)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
all_o
);
assert_eq!(
store
.quads_for_pattern(Some(&main_s), None, None, None)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
all_o
);
assert_eq!(
store
.quads_for_pattern(Some(&main_s), Some(&main_p), None, None)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
all_o
);
assert_eq!(
store
.quads_for_pattern(Some(&main_s), Some(&main_p), Some(&main_o), None)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
target
);
assert_eq!(
@ -873,7 +880,7 @@ fn store() -> Result<()> {
Some(&main_o),
Some(&GraphName::DefaultGraph)
)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
target
);
assert_eq!(
@ -884,13 +891,13 @@ fn store() -> Result<()> {
None,
Some(&GraphName::DefaultGraph)
)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
all_o
);
assert_eq!(
store
.quads_for_pattern(Some(&main_s), None, Some(&main_o), None)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
target
);
assert_eq!(
@ -901,37 +908,37 @@ fn store() -> Result<()> {
Some(&main_o),
Some(&GraphName::DefaultGraph)
)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
target
);
assert_eq!(
store
.quads_for_pattern(Some(&main_s), None, None, Some(&GraphName::DefaultGraph))
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
all_o
);
assert_eq!(
store
.quads_for_pattern(None, Some(&main_p), None, None)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
all_o
);
assert_eq!(
store
.quads_for_pattern(None, Some(&main_p), Some(&main_o), None)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
target
);
assert_eq!(
store
.quads_for_pattern(None, None, Some(&main_o), None)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
target
);
assert_eq!(
store
.quads_for_pattern(None, None, None, Some(&GraphName::DefaultGraph))
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
all_o
);
assert_eq!(
@ -942,7 +949,7 @@ fn store() -> Result<()> {
Some(&main_o),
Some(&GraphName::DefaultGraph)
)
.collect::<Result<Vec<_>>>()?,
.collect::<Result<Vec<_>, _>>()?,
target
);

@ -2,16 +2,14 @@ use crate::model::*;
use crate::store_utils::*;
use oxigraph::model::*;
use oxigraph::sparql::QueryOptions;
use oxigraph::{DatasetSyntax, FileSyntax, GraphSyntax, Result, SledStore};
use pyo3::create_exception;
use pyo3::exceptions::ValueError;
use oxigraph::{DatasetSyntax, FileSyntax, GraphSyntax, SledStore};
use pyo3::exceptions::{IOError, ValueError};
use pyo3::prelude::*;
use pyo3::types::PyTuple;
use pyo3::{PyIterProtocol, PyObjectProtocol, PySequenceProtocol};
use std::io;
use std::io::Cursor;
create_exception!(oxigraph, SledError, pyo3::exceptions::RuntimeError);
#[pyclass(name = SledStore)]
#[derive(Clone)]
pub struct PySledStore {
@ -24,9 +22,9 @@ impl PySledStore {
fn new(path: Option<&str>) -> PyResult<Self> {
Ok(Self {
inner: if let Some(path) = path {
SledStore::open(path).map_err(|e| SledError::py_err(e.to_string()))?
SledStore::open(path).map_err(|e| IOError::py_err(e.to_string()))?
} else {
SledStore::new().map_err(|e| SledError::py_err(e.to_string()))?
SledStore::new().map_err(|e| IOError::py_err(e.to_string()))?
},
})
}
@ -34,13 +32,13 @@ impl PySledStore {
fn add(&self, quad: &PyTuple) -> PyResult<()> {
self.inner
.insert(&extract_quad(quad)?)
.map_err(|e| SledError::py_err(e.to_string()))
.map_err(|e| IOError::py_err(e.to_string()))
}
fn remove(&self, quad: &PyTuple) -> PyResult<()> {
self.inner
.remove(&extract_quad(quad)?)
.map_err(|e| SledError::py_err(e.to_string()))
.map_err(|e| IOError::py_err(e.to_string()))
}
fn r#match(
@ -136,7 +134,7 @@ impl PySequenceProtocol for PySledStore {
fn __contains__(&self, quad: &PyTuple) -> PyResult<bool> {
self.inner
.contains(&extract_quad(quad)?)
.map_err(|e| SledError::py_err(e.to_string()))
.map_err(|e| IOError::py_err(e.to_string()))
}
}
@ -151,7 +149,7 @@ impl PyIterProtocol for PySledStore {
#[pyclass(unsendable)]
pub struct QuadIter {
inner: Box<dyn Iterator<Item = Result<Quad>>>,
inner: Box<dyn Iterator<Item = Result<Quad, io::Error>>>,
}
#[pyproto]
@ -168,7 +166,7 @@ impl PyIterProtocol for QuadIter {
.map(move |q| {
Ok(quad_to_python(
slf.py(),
q.map_err(|e| SledError::py_err(e.to_string()))?,
q.map_err(|e| IOError::py_err(e.to_string()))?,
))
})
.transpose()

@ -264,7 +264,7 @@ impl WikibaseLoader {
let to_remove = self
.store
.quads_for_pattern(None, None, None, Some(&graph_name))
.collect::<oxigraph::Result<Vec<_>>>()?;
.collect::<std::result::Result<Vec<_>, _>>()?;
for q in to_remove {
transaction.remove(&q);
}

Loading…
Cancel
Save