Renames SledStore to Store and cleans up files hierarchy

pull/171/head
Tpt 4 years ago
parent a5c49a73b1
commit 0efc5b4654
  1. 12
      lib/README.md
  2. 4
      lib/benches/store.rs
  3. 12
      lib/src/lib.rs
  4. 18
      lib/src/sophia.rs
  5. 4
      lib/src/sparql/dataset.rs
  6. 2
      lib/src/sparql/error.rs
  7. 4
      lib/src/sparql/eval.rs
  8. 4
      lib/src/sparql/mod.rs
  9. 20
      lib/src/sparql/model.rs
  10. 2
      lib/src/sparql/plan.rs
  11. 2
      lib/src/sparql/plan_builder.rs
  12. 8
      lib/src/sparql/service.rs
  13. 6
      lib/src/sparql/update.rs
  14. 6
      lib/src/storage/binary_encoder.rs
  15. 4
      lib/src/storage/io.rs
  16. 181
      lib/src/storage/mod.rs
  17. 2
      lib/src/storage/numeric_encoder.rs
  18. 0
      lib/src/storage/small_string.rs
  19. 217
      lib/src/store.rs
  20. 12
      lib/src/store/mod.rs
  21. 22
      lib/tests/store.rs
  22. 12
      python/src/store.rs
  23. 2
      server/src/main.rs
  24. 4
      testsuite/src/files.rs
  25. 14
      testsuite/src/sparql_evaluator.rs
  26. 6
      wikibase/src/loader.rs
  27. 10
      wikibase/src/main.rs

@ -29,11 +29,11 @@ A preliminary benchmark [is provided](../bench/README.md).
Usage example: Usage example:
```rust ```rust
use oxigraph::SledStore; use oxigraph::store::Store;
use oxigraph::model::*;
use oxigraph::sparql::QueryResults; use oxigraph::sparql::QueryResults;
use oxigraph::model::*;
let store = SledStore::new()?; let store = Store::open("example.db")?;
// insertion // insertion
let ex = NamedNode::new("http://example.com")?; let ex = NamedNode::new("http://example.com")?;
@ -41,13 +41,13 @@ let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), None);
store.insert(&quad)?; store.insert(&quad)?;
// quad filter // quad filter
let results = store.quads_for_pattern(Some(ex.as_ref().into()), None, None, None).collect::<Result<Vec<Quad>,_>>()?; let results: Result<Vec<Quad>,_> = store.quads_for_pattern(None, None, None, None).collect();
assert_eq!(vec![quad], results); assert_eq!(vec![quad], results?);
// SPARQL query // SPARQL query
if let QueryResults::Solutions(mut solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }")? { if let QueryResults::Solutions(mut solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }")? {
assert_eq!(solutions.next().unwrap()?.get("s"), Some(&ex.into())); assert_eq!(solutions.next().unwrap()?.get("s"), Some(&ex.into()));
} };
``` ```
## License ## License

@ -1,6 +1,6 @@
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
use oxigraph::model::{Dataset, Graph, NamedNode, Quad, Triple}; use oxigraph::model::{Dataset, Graph, NamedNode, Quad, Triple};
use oxigraph::SledStore; use oxigraph::store::Store;
use rand::random; use rand::random;
use std::iter::FromIterator; use std::iter::FromIterator;
@ -54,7 +54,7 @@ fn sled_load_bench(c: &mut Criterion) {
let quads = create_quads(*size); let quads = create_quads(*size);
group.bench_function(BenchmarkId::from_parameter(size), |b| { group.bench_function(BenchmarkId::from_parameter(size), |b| {
b.iter(|| { b.iter(|| {
let store = SledStore::new().unwrap(); let store = Store::new().unwrap();
for quad in &quads { for quad in &quads {
store.insert(quad).unwrap(); store.insert(quad).unwrap();
} }

@ -9,12 +9,15 @@
//! //!
//! Oxigraph also provides [a standalone HTTP server](https://crates.io/crates/oxigraph_server) based on this library. //! Oxigraph also provides [a standalone HTTP server](https://crates.io/crates/oxigraph_server) based on this library.
//! //!
//!
//! The main entry point of Oxigraph is the [`Store`](store::Store) struct:
//!
//! ``` //! ```
//! use oxigraph::SledStore; //! use oxigraph::store::Store;
//! use oxigraph::model::*; //! use oxigraph::model::*;
//! use oxigraph::sparql::QueryResults; //! use oxigraph::sparql::QueryResults;
//! //!
//! let store = SledStore::new()?; //! let store = Store::new()?;
//! //!
//! // insertion //! // insertion
//! let ex = NamedNode::new("http://example.com")?; //! let ex = NamedNode::new("http://example.com")?;
@ -112,7 +115,8 @@
mod error; mod error;
pub mod io; pub mod io;
pub mod model; pub mod model;
#[cfg(feature = "sophia")]
mod sophia;
pub mod sparql; pub mod sparql;
mod storage;
pub mod store; pub mod store;
pub use crate::store::sled::SledStore;

@ -5,7 +5,7 @@ use crate::model::{
TermRef, TermRef,
}; };
use crate::sparql::{EvaluationError, QueryResults}; use crate::sparql::{EvaluationError, QueryResults};
use crate::store::SledStore; use crate::store::Store;
use sophia_api::dataset::{ use sophia_api::dataset::{
CollectibleDataset, DQuadSource, DResultTermSet, DTerm, Dataset, MDResult, MutableDataset, CollectibleDataset, DQuadSource, DResultTermSet, DTerm, Dataset, MDResult, MutableDataset,
}; };
@ -20,7 +20,7 @@ use std::iter::empty;
type SophiaQuad = ([Term; 3], Option<Term>); type SophiaQuad = ([Term; 3], Option<Term>);
type StreamedSophiaQuad<'a> = StreamedQuad<'a, ByValue<SophiaQuad>>; type StreamedSophiaQuad<'a> = StreamedQuad<'a, ByValue<SophiaQuad>>;
impl Dataset for SledStore { impl Dataset for Store {
type Quad = ByValue<SophiaQuad>; type Quad = ByValue<SophiaQuad>;
type Error = Error; type Error = Error;
@ -373,7 +373,7 @@ impl Dataset for SledStore {
} }
} }
impl MutableDataset for SledStore { impl MutableDataset for Store {
type MutationError = Error; type MutationError = Error;
fn insert<TS, TP, TO, TG>( fn insert<TS, TP, TO, TG>(
&mut self, &mut self,
@ -397,7 +397,7 @@ impl MutableDataset for SledStore {
Some(quad) => quad, Some(quad) => quad,
None => return Ok(false), None => return Ok(false),
}; };
SledStore::insert(self, quadref).map(|_| true) Store::insert(self, quadref).map(|_| true)
} }
fn remove<TS, TP, TO, TG>( fn remove<TS, TP, TO, TG>(
@ -422,13 +422,13 @@ impl MutableDataset for SledStore {
Some(quad) => quad, Some(quad) => quad,
None => return Ok(false), None => return Ok(false),
}; };
SledStore::remove(self, quadref).map(|_| true) Store::remove(self, quadref).map(|_| true)
} }
} }
impl CollectibleDataset for SledStore { impl CollectibleDataset for Store {
fn from_quad_source<QS: QuadSource>(quads: QS) -> StreamResult<Self, QS::Error, Self::Error> { fn from_quad_source<QS: QuadSource>(quads: QS) -> StreamResult<Self, QS::Error, Self::Error> {
let mut d = SledStore::new().map_err(sophia_api::quad::stream::StreamError::SinkError)?; let mut d = Store::new().map_err(sophia_api::quad::stream::StreamError::SinkError)?;
d.insert_all(quads)?; d.insert_all(quads)?;
Ok(d) Ok(d)
} }
@ -576,7 +576,7 @@ where
/// # Precondition /// # Precondition
/// + the query must be a SELECT query with a single selected variable /// + the query must be a SELECT query with a single selected variable
/// + it must not produce NULL results /// + it must not produce NULL results
fn sparql_to_hashset(store: &SledStore, sparql: &str) -> Result<HashSet<Term>, Error> { fn sparql_to_hashset(store: &Store, sparql: &str) -> Result<HashSet<Term>, Error> {
if let QueryResults::Solutions(solutions) = store.query(sparql).map_err(io_err_map)? { if let QueryResults::Solutions(solutions) = store.query(sparql).map_err(io_err_map)? {
solutions solutions
.map(|r| r.map(|v| v.get(0).unwrap().clone())) .map(|r| r.map(|v| v.get(0).unwrap().clone()))
@ -588,4 +588,4 @@ fn sparql_to_hashset(store: &SledStore, sparql: &str) -> Result<HashSet<Term>, E
} }
#[cfg(test)] #[cfg(test)]
sophia_api::test_dataset_impl!(test, SledStore, false, false); sophia_api::test_dataset_impl!(test, Store, false, false);

@ -1,9 +1,9 @@
use crate::sparql::algebra::QueryDataset; use crate::sparql::algebra::QueryDataset;
use crate::sparql::EvaluationError; use crate::sparql::EvaluationError;
use crate::store::numeric_encoder::{ use crate::storage::numeric_encoder::{
EncodedQuad, EncodedTerm, ReadEncoder, StrContainer, StrEncodingAware, StrHash, StrLookup, EncodedQuad, EncodedTerm, ReadEncoder, StrContainer, StrEncodingAware, StrHash, StrLookup,
}; };
use crate::store::storage::Storage; use crate::storage::Storage;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
use std::iter::empty; use std::iter::empty;

@ -1,6 +1,6 @@
use crate::error::invalid_data_error; use crate::error::invalid_data_error;
use crate::sparql::ParseError; use crate::sparql::ParseError;
use crate::store::numeric_encoder::DecoderError; use crate::storage::numeric_encoder::DecoderError;
use std::convert::Infallible; use std::convert::Infallible;
use std::error; use std::error;
use std::fmt; use std::fmt;

@ -8,8 +8,8 @@ use crate::sparql::error::EvaluationError;
use crate::sparql::model::*; use crate::sparql::model::*;
use crate::sparql::plan::*; use crate::sparql::plan::*;
use crate::sparql::service::ServiceHandler; use crate::sparql::service::ServiceHandler;
use crate::store::numeric_encoder::*; use crate::storage::numeric_encoder::*;
use crate::store::small_string::SmallString; use crate::storage::small_string::SmallString;
use digest::Digest; use digest::Digest;
use md5::Md5; use md5::Md5;
use oxilangtag::LanguageTag; use oxilangtag::LanguageTag;

@ -1,6 +1,6 @@
//! [SPARQL](https://www.w3.org/TR/sparql11-overview/) implementation. //! [SPARQL](https://www.w3.org/TR/sparql11-overview/) implementation.
//! //!
//! Stores execute SPARQL. See [`SledStore`](super::store::sled::SledStore::query()) for an example. //! Stores execute SPARQL. See [`Store`](crate::store::Store::query()) for an example.
mod algebra; mod algebra;
mod csv_results; mod csv_results;
@ -30,7 +30,7 @@ use crate::sparql::plan_builder::PlanBuilder;
pub use crate::sparql::service::ServiceHandler; pub use crate::sparql::service::ServiceHandler;
use crate::sparql::service::{EmptyServiceHandler, ErrorConversionServiceHandler}; use crate::sparql::service::{EmptyServiceHandler, ErrorConversionServiceHandler};
use crate::sparql::update::SimpleUpdateEvaluator; use crate::sparql::update::SimpleUpdateEvaluator;
use crate::store::storage::Storage; use crate::storage::Storage;
pub use spargebra::ParseError; pub use spargebra::ParseError;
use std::convert::TryInto; use std::convert::TryInto;
use std::rc::Rc; use std::rc::Rc;

@ -44,11 +44,11 @@ impl QueryResults {
/// This method fails if it is called on the `Graph` results /// This method fails if it is called on the `Graph` results
/// ///
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::Store;
/// use oxigraph::model::*; /// use oxigraph::model::*;
/// use oxigraph::sparql::QueryResultsFormat; /// use oxigraph::sparql::QueryResultsFormat;
/// ///
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// let ex = NamedNodeRef::new("http://example.com")?; /// let ex = NamedNodeRef::new("http://example.com")?;
/// store.insert(QuadRef::new(ex, ex, ex, GraphNameRef::DefaultGraph))?; /// store.insert(QuadRef::new(ex, ex, ex, GraphNameRef::DefaultGraph))?;
/// ///
@ -75,14 +75,14 @@ impl QueryResults {
/// This method fails if it is called on the `Solution` or `Boolean` results /// This method fails if it is called on the `Solution` or `Boolean` results
/// ///
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::Store;
/// use oxigraph::io::GraphFormat; /// use oxigraph::io::GraphFormat;
/// use oxigraph::model::*; /// use oxigraph::model::*;
/// use std::io::Cursor; /// use std::io::Cursor;
/// ///
/// let graph = "<http://example.com> <http://example.com> <http://example.com> .\n".as_bytes(); /// let graph = "<http://example.com> <http://example.com> <http://example.com> .\n".as_bytes();
/// ///
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// store.load_graph(Cursor::new(graph), GraphFormat::NTriples, &GraphName::DefaultGraph, None)?; /// store.load_graph(Cursor::new(graph), GraphFormat::NTriples, &GraphName::DefaultGraph, None)?;
/// ///
/// let mut results = Vec::new(); /// let mut results = Vec::new();
@ -216,10 +216,10 @@ impl QueryResultsFormat {
/// An iterator over [`QuerySolution`]s /// An iterator over [`QuerySolution`]s
/// ///
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::Store;
/// use oxigraph::sparql::QueryResults; /// use oxigraph::sparql::QueryResults;
/// ///
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// if let QueryResults::Solutions(solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }")? { /// if let QueryResults::Solutions(solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }")? {
/// for solution in solutions { /// for solution in solutions {
/// println!("{:?}", solution?.get("s")); /// println!("{:?}", solution?.get("s"));
@ -243,10 +243,10 @@ impl QuerySolutionIter {
/// The variables used in the solutions /// The variables used in the solutions
/// ///
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::Store;
/// use oxigraph::sparql::{QueryResults, Variable}; /// use oxigraph::sparql::{QueryResults, Variable};
/// ///
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// if let QueryResults::Solutions(solutions) = store.query("SELECT ?s ?o WHERE { ?s ?p ?o }")? { /// if let QueryResults::Solutions(solutions) = store.query("SELECT ?s ?o WHERE { ?s ?p ?o }")? {
/// assert_eq!(solutions.variables(), &[Variable::new("s")?, Variable::new("o")?]); /// assert_eq!(solutions.variables(), &[Variable::new("s")?, Variable::new("o")?]);
/// } /// }
@ -359,10 +359,10 @@ impl VariableSolutionIndex for Variable {
/// An iterator over the triples that compose a graph solution /// An iterator over the triples that compose a graph solution
/// ///
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::Store;
/// use oxigraph::sparql::QueryResults; /// use oxigraph::sparql::QueryResults;
/// ///
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// if let QueryResults::Graph(triples) = store.query("CONSTRUCT WHERE { ?s ?p ?o }")? { /// if let QueryResults::Graph(triples) = store.query("CONSTRUCT WHERE { ?s ?p ?o }")? {
/// for triple in triples { /// for triple in triples {
/// println!("{}", triple?); /// println!("{}", triple?);

@ -1,5 +1,5 @@
use crate::sparql::model::Variable; use crate::sparql::model::Variable;
use crate::store::numeric_encoder::EncodedTerm; use crate::storage::numeric_encoder::EncodedTerm;
use spargebra::algebra::GraphPattern; use spargebra::algebra::GraphPattern;
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::rc::Rc; use std::rc::Rc;

@ -3,7 +3,7 @@ use crate::sparql::dataset::DatasetView;
use crate::sparql::error::EvaluationError; use crate::sparql::error::EvaluationError;
use crate::sparql::model::Variable as OxVariable; use crate::sparql::model::Variable as OxVariable;
use crate::sparql::plan::*; use crate::sparql::plan::*;
use crate::store::numeric_encoder::{EncodedTerm, WriteEncoder}; use crate::storage::numeric_encoder::{EncodedTerm, WriteEncoder};
use rand::random; use rand::random;
use spargebra::algebra::*; use spargebra::algebra::*;
use spargebra::term::*; use spargebra::term::*;

@ -15,12 +15,12 @@ use std::error::Error;
/// before evaluating a SPARQL query that uses SERVICE calls. /// before evaluating a SPARQL query that uses SERVICE calls.
/// ///
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::Store;
/// use oxigraph::model::*; /// use oxigraph::model::*;
/// use oxigraph::sparql::{QueryOptions, QueryResults, ServiceHandler, Query, EvaluationError}; /// use oxigraph::sparql::{QueryOptions, QueryResults, ServiceHandler, Query, EvaluationError};
/// ///
/// struct TestServiceHandler { /// struct TestServiceHandler {
/// store: SledStore /// store: Store
/// } /// }
/// ///
/// impl ServiceHandler for TestServiceHandler { /// impl ServiceHandler for TestServiceHandler {
@ -35,9 +35,9 @@ use std::error::Error;
/// } /// }
/// } /// }
/// ///
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// let service = TestServiceHandler { /// let service = TestServiceHandler {
/// store: SledStore::new()? /// store: Store::new()?
/// }; /// };
/// let ex = NamedNodeRef::new("http://example.com")?; /// let ex = NamedNodeRef::new("http://example.com")?;
/// service.store.insert(QuadRef::new(ex, ex, ex, GraphNameRef::DefaultGraph))?; /// service.store.insert(QuadRef::new(ex, ex, ex, GraphNameRef::DefaultGraph))?;

@ -8,11 +8,11 @@ use crate::sparql::http::Client;
use crate::sparql::plan::EncodedTuple; use crate::sparql::plan::EncodedTuple;
use crate::sparql::plan_builder::PlanBuilder; use crate::sparql::plan_builder::PlanBuilder;
use crate::sparql::{EvaluationError, UpdateOptions}; use crate::sparql::{EvaluationError, UpdateOptions};
use crate::store::io::load_graph; use crate::storage::io::load_graph;
use crate::store::numeric_encoder::{ use crate::storage::numeric_encoder::{
EncodedQuad, EncodedTerm, ReadEncoder, StrLookup, WriteEncoder, EncodedQuad, EncodedTerm, ReadEncoder, StrLookup, WriteEncoder,
}; };
use crate::store::storage::Storage; use crate::storage::Storage;
use http::header::{ACCEPT, CONTENT_TYPE, USER_AGENT}; use http::header::{ACCEPT, CONTENT_TYPE, USER_AGENT};
use http::{Method, Request, StatusCode}; use http::{Method, Request, StatusCode};
use oxiri::Iri; use oxiri::Iri;

@ -1,7 +1,7 @@
use crate::error::invalid_data_error; use crate::error::invalid_data_error;
use crate::model::xsd::*; use crate::model::xsd::*;
use crate::store::numeric_encoder::{EncodedQuad, EncodedTerm, StrHash}; use crate::storage::numeric_encoder::{EncodedQuad, EncodedTerm, StrHash};
use crate::store::small_string::SmallString; use crate::storage::small_string::SmallString;
use std::io; use std::io;
use std::io::{Cursor, Read}; use std::io::{Cursor, Read};
use std::mem::size_of; use std::mem::size_of;
@ -627,7 +627,7 @@ pub fn write_term(sink: &mut Vec<u8>, term: EncodedTerm) {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::store::numeric_encoder::*; use crate::storage::numeric_encoder::*;
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::Infallible; use std::convert::Infallible;
use std::sync::RwLock; use std::sync::RwLock;

@ -3,8 +3,8 @@
use crate::error::invalid_input_error; use crate::error::invalid_input_error;
use crate::io::{DatasetFormat, DatasetSerializer, GraphFormat, GraphSerializer}; use crate::io::{DatasetFormat, DatasetSerializer, GraphFormat, GraphSerializer};
use crate::model::{GraphNameRef, Quad, Triple}; use crate::model::{GraphNameRef, Quad, Triple};
use crate::store::numeric_encoder::WriteEncoder; use crate::storage::numeric_encoder::WriteEncoder;
use crate::store::storage::StorageLike; use crate::storage::StorageLike;
use oxiri::Iri; use oxiri::Iri;
use rio_api::parser::{QuadsParser, TriplesParser}; use rio_api::parser::{QuadsParser, TriplesParser};
use rio_turtle::{NQuadsParser, NTriplesParser, TriGParser, TurtleError, TurtleParser}; use rio_turtle::{NQuadsParser, NTriplesParser, TriGParser, TurtleError, TurtleParser};

@ -1,18 +1,31 @@
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
use std::io;
use std::path::Path; use std::path::Path;
use sled::transaction::{ use sled::transaction::{
ConflictableTransactionError, TransactionError, TransactionalTree, UnabortableTransactionError, ConflictableTransactionError as Sled2ConflictableTransactionError,
TransactionError as Sled2TransactionError, TransactionalTree,
UnabortableTransactionError as Sled2UnabortableTransactionError,
}; };
use sled::{Config, Db, Iter, Transactional, Tree}; use sled::{Config, Db, Iter, Transactional, Tree};
use crate::error::invalid_data_error; use crate::error::invalid_data_error;
use crate::sparql::EvaluationError; use crate::sparql::EvaluationError;
use crate::store::binary_encoder::*; use crate::storage::binary_encoder::{
use crate::store::io::StoreOrParseError; decode_term, encode_term, encode_term_pair, encode_term_quad, encode_term_triple,
use crate::store::numeric_encoder::*; write_gosp_quad, write_gpos_quad, write_gspo_quad, write_osp_quad, write_ospg_quad,
write_pos_quad, write_posg_quad, write_spo_quad, write_spog_quad, write_term, QuadEncoding,
LATEST_STORAGE_VERSION, WRITTEN_TERM_MAX_SIZE,
};
use crate::storage::io::StoreOrParseError;
use crate::storage::numeric_encoder::{
EncodedQuad, EncodedTerm, StrContainer, StrEncodingAware, StrHash, StrLookup,
};
mod binary_encoder;
pub(crate) mod io;
pub(crate) mod numeric_encoder;
pub(crate) mod small_string;
/// Low level storage primitives /// Low level storage primitives
#[derive(Clone)] #[derive(Clone)]
@ -32,15 +45,15 @@ pub struct Storage {
} }
impl Storage { impl Storage {
pub fn new() -> Result<Self, io::Error> { pub fn new() -> Result<Self, std::io::Error> {
Self::do_open(&Config::new().temporary(true)) Self::do_open(&Config::new().temporary(true))
} }
pub fn open(path: &Path) -> Result<Self, io::Error> { pub fn open(path: &Path) -> Result<Self, std::io::Error> {
Self::do_open(&Config::new().path(path)) Self::do_open(&Config::new().path(path))
} }
fn do_open(config: &Config) -> Result<Self, io::Error> { fn do_open(config: &Config) -> Result<Self, std::io::Error> {
let db = config.open()?; let db = config.open()?;
let this = Self { let this = Self {
default: db.clone(), default: db.clone(),
@ -84,7 +97,7 @@ impl Storage {
} }
} }
fn ensure_version(&self) -> Result<u64, io::Error> { fn ensure_version(&self) -> Result<u64, std::io::Error> {
Ok(if let Some(version) = self.default.get("oxversion")? { Ok(if let Some(version) = self.default.get("oxversion")? {
let mut buffer = [0; 8]; let mut buffer = [0; 8];
buffer.copy_from_slice(&version); buffer.copy_from_slice(&version);
@ -95,15 +108,15 @@ impl Storage {
}) })
} }
fn set_version(&self, version: u64) -> Result<(), io::Error> { fn set_version(&self, version: u64) -> Result<(), std::io::Error> {
self.default.insert("oxversion", &version.to_be_bytes())?; self.default.insert("oxversion", &version.to_be_bytes())?;
Ok(()) Ok(())
} }
pub fn transaction<T, E>( pub fn transaction<T, E>(
&self, &self,
f: impl Fn(StorageTransaction<'_>) -> Result<T, SledConflictableTransactionError<E>>, f: impl Fn(StorageTransaction<'_>) -> Result<T, ConflictableTransactionError<E>>,
) -> Result<T, SledTransactionError<E>> { ) -> Result<T, TransactionError<E>> {
Ok(( Ok((
&self.id2str, &self.id2str,
&self.spog, &self.spog,
@ -144,7 +157,7 @@ impl Storage {
self.gspo.is_empty() && self.dspo.is_empty() self.gspo.is_empty() && self.dspo.is_empty()
} }
pub fn contains(&self, quad: &EncodedQuad) -> Result<bool, io::Error> { pub fn contains(&self, quad: &EncodedQuad) -> Result<bool, std::io::Error> {
let mut buffer = Vec::with_capacity(4 * WRITTEN_TERM_MAX_SIZE); let mut buffer = Vec::with_capacity(4 * WRITTEN_TERM_MAX_SIZE);
if quad.graph_name.is_default_graph() { if quad.graph_name.is_default_graph() {
write_spo_quad(&mut buffer, quad); write_spo_quad(&mut buffer, quad);
@ -394,7 +407,7 @@ impl Storage {
} }
} }
pub fn contains_named_graph(&self, graph_name: EncodedTerm) -> Result<bool, io::Error> { pub fn contains_named_graph(&self, graph_name: EncodedTerm) -> Result<bool, std::io::Error> {
Ok(self.graphs.contains_key(&encode_term(graph_name))?) Ok(self.graphs.contains_key(&encode_term(graph_name))?)
} }
@ -446,7 +459,7 @@ impl Storage {
} }
} }
pub fn insert(&self, quad: &EncodedQuad) -> Result<bool, io::Error> { pub fn insert(&self, quad: &EncodedQuad) -> Result<bool, std::io::Error> {
let mut buffer = Vec::with_capacity(4 * WRITTEN_TERM_MAX_SIZE + 1); let mut buffer = Vec::with_capacity(4 * WRITTEN_TERM_MAX_SIZE + 1);
if quad.graph_name.is_default_graph() { if quad.graph_name.is_default_graph() {
@ -501,7 +514,7 @@ impl Storage {
} }
} }
pub fn remove(&self, quad: &EncodedQuad) -> Result<bool, io::Error> { pub fn remove(&self, quad: &EncodedQuad) -> Result<bool, std::io::Error> {
let mut buffer = Vec::with_capacity(4 * WRITTEN_TERM_MAX_SIZE + 1); let mut buffer = Vec::with_capacity(4 * WRITTEN_TERM_MAX_SIZE + 1);
if quad.graph_name.is_default_graph() { if quad.graph_name.is_default_graph() {
@ -553,11 +566,11 @@ impl Storage {
} }
} }
pub fn insert_named_graph(&self, graph_name: EncodedTerm) -> Result<bool, io::Error> { pub fn insert_named_graph(&self, graph_name: EncodedTerm) -> Result<bool, std::io::Error> {
Ok(self.graphs.insert(&encode_term(graph_name), &[])?.is_none()) Ok(self.graphs.insert(&encode_term(graph_name), &[])?.is_none())
} }
pub fn clear_graph(&self, graph_name: EncodedTerm) -> Result<(), io::Error> { pub fn clear_graph(&self, graph_name: EncodedTerm) -> Result<(), std::io::Error> {
if graph_name.is_default_graph() { if graph_name.is_default_graph() {
self.dspo.clear()?; self.dspo.clear()?;
self.dpos.clear()?; self.dpos.clear()?;
@ -570,14 +583,14 @@ impl Storage {
Ok(()) Ok(())
} }
pub fn remove_named_graph(&self, graph_name: EncodedTerm) -> Result<bool, io::Error> { pub fn remove_named_graph(&self, graph_name: EncodedTerm) -> Result<bool, std::io::Error> {
for quad in self.quads_for_graph(graph_name) { for quad in self.quads_for_graph(graph_name) {
self.remove(&quad?)?; self.remove(&quad?)?;
} }
Ok(self.graphs.remove(&encode_term(graph_name))?.is_some()) Ok(self.graphs.remove(&encode_term(graph_name))?.is_some())
} }
pub fn clear(&self) -> Result<(), io::Error> { pub fn clear(&self) -> Result<(), std::io::Error> {
self.dspo.clear()?; self.dspo.clear()?;
self.dpos.clear()?; self.dpos.clear()?;
self.dosp.clear()?; self.dosp.clear()?;
@ -592,7 +605,7 @@ impl Storage {
Ok(()) Ok(())
} }
pub fn get_str(&self, key: StrHash) -> Result<Option<String>, io::Error> { pub fn get_str(&self, key: StrHash) -> Result<Option<String>, std::io::Error> {
self.id2str self.id2str
.get(key.to_be_bytes())? .get(key.to_be_bytes())?
.map(|v| String::from_utf8(v.to_vec())) .map(|v| String::from_utf8(v.to_vec()))
@ -600,11 +613,11 @@ impl Storage {
.map_err(invalid_data_error) .map_err(invalid_data_error)
} }
pub fn contains_str(&self, key: StrHash) -> Result<bool, io::Error> { pub fn contains_str(&self, key: StrHash) -> Result<bool, std::io::Error> {
Ok(self.id2str.contains_key(key.to_be_bytes())?) Ok(self.id2str.contains_key(key.to_be_bytes())?)
} }
pub fn insert_str(&self, key: StrHash, value: &str) -> Result<bool, io::Error> { pub fn insert_str(&self, key: StrHash, value: &str) -> Result<bool, std::io::Error> {
Ok(self.id2str.insert(key.to_be_bytes(), value)?.is_none()) Ok(self.id2str.insert(key.to_be_bytes(), value)?.is_none())
} }
} }
@ -631,9 +644,9 @@ impl ChainedDecodingQuadIterator {
} }
impl Iterator for ChainedDecodingQuadIterator { impl Iterator for ChainedDecodingQuadIterator {
type Item = Result<EncodedQuad, io::Error>; type Item = Result<EncodedQuad, std::io::Error>;
fn next(&mut self) -> Option<Result<EncodedQuad, io::Error>> { fn next(&mut self) -> Option<Result<EncodedQuad, std::io::Error>> {
if let Some(result) = self.first.next() { if let Some(result) = self.first.next() {
Some(result) Some(result)
} else if let Some(second) = self.second.as_mut() { } else if let Some(second) = self.second.as_mut() {
@ -650,9 +663,9 @@ pub struct DecodingQuadIterator {
} }
impl Iterator for DecodingQuadIterator { impl Iterator for DecodingQuadIterator {
type Item = Result<EncodedQuad, io::Error>; type Item = Result<EncodedQuad, std::io::Error>;
fn next(&mut self) -> Option<Result<EncodedQuad, io::Error>> { fn next(&mut self) -> Option<Result<EncodedQuad, std::io::Error>> {
Some(match self.iter.next()? { Some(match self.iter.next()? {
Ok((encoded, _)) => self.encoding.decode(&encoded), Ok((encoded, _)) => self.encoding.decode(&encoded),
Err(error) => Err(error.into()), Err(error) => Err(error.into()),
@ -665,9 +678,9 @@ pub struct DecodingGraphIterator {
} }
impl Iterator for DecodingGraphIterator { impl Iterator for DecodingGraphIterator {
type Item = Result<EncodedTerm, io::Error>; type Item = Result<EncodedTerm, std::io::Error>;
fn next(&mut self) -> Option<Result<EncodedTerm, io::Error>> { fn next(&mut self) -> Option<Result<EncodedTerm, std::io::Error>> {
Some(match self.iter.next()? { Some(match self.iter.next()? {
Ok((encoded, _)) => decode_term(&encoded), Ok((encoded, _)) => decode_term(&encoded),
Err(error) => Err(error.into()), Err(error) => Err(error.into()),
@ -690,7 +703,7 @@ pub struct StorageTransaction<'a> {
} }
impl<'a> StorageTransaction<'a> { impl<'a> StorageTransaction<'a> {
pub fn insert(&self, quad: &EncodedQuad) -> Result<bool, SledUnabortableTransactionError> { pub fn insert(&self, quad: &EncodedQuad) -> Result<bool, UnabortableTransactionError> {
let mut buffer = Vec::with_capacity(4 * WRITTEN_TERM_MAX_SIZE + 1); let mut buffer = Vec::with_capacity(4 * WRITTEN_TERM_MAX_SIZE + 1);
if quad.graph_name.is_default_graph() { if quad.graph_name.is_default_graph() {
@ -746,7 +759,7 @@ impl<'a> StorageTransaction<'a> {
} }
} }
pub fn remove(&self, quad: &EncodedQuad) -> Result<bool, SledUnabortableTransactionError> { pub fn remove(&self, quad: &EncodedQuad) -> Result<bool, UnabortableTransactionError> {
let mut buffer = Vec::with_capacity(4 * WRITTEN_TERM_MAX_SIZE + 1); let mut buffer = Vec::with_capacity(4 * WRITTEN_TERM_MAX_SIZE + 1);
if quad.graph_name.is_default_graph() { if quad.graph_name.is_default_graph() {
@ -801,19 +814,19 @@ impl<'a> StorageTransaction<'a> {
pub fn insert_named_graph( pub fn insert_named_graph(
&self, &self,
graph_name: EncodedTerm, graph_name: EncodedTerm,
) -> Result<bool, SledUnabortableTransactionError> { ) -> Result<bool, UnabortableTransactionError> {
Ok(self.graphs.insert(encode_term(graph_name), &[])?.is_none()) Ok(self.graphs.insert(encode_term(graph_name), &[])?.is_none())
} }
pub fn get_str(&self, key: StrHash) -> Result<Option<String>, SledUnabortableTransactionError> { pub fn get_str(&self, key: StrHash) -> Result<Option<String>, UnabortableTransactionError> {
self.id2str self.id2str
.get(key.to_be_bytes())? .get(key.to_be_bytes())?
.map(|v| String::from_utf8(v.to_vec())) .map(|v| String::from_utf8(v.to_vec()))
.transpose() .transpose()
.map_err(|e| SledUnabortableTransactionError::Storage(invalid_data_error(e))) .map_err(|e| UnabortableTransactionError::Storage(invalid_data_error(e)))
} }
pub fn contains_str(&self, key: StrHash) -> Result<bool, SledUnabortableTransactionError> { pub fn contains_str(&self, key: StrHash) -> Result<bool, UnabortableTransactionError> {
Ok(self.id2str.get(key.to_be_bytes())?.is_some()) Ok(self.id2str.get(key.to_be_bytes())?.is_some())
} }
@ -821,21 +834,21 @@ impl<'a> StorageTransaction<'a> {
&self, &self,
key: StrHash, key: StrHash,
value: &str, value: &str,
) -> Result<bool, SledUnabortableTransactionError> { ) -> Result<bool, UnabortableTransactionError> {
Ok(self.id2str.insert(&key.to_be_bytes(), value)?.is_none()) Ok(self.id2str.insert(&key.to_be_bytes(), value)?.is_none())
} }
} }
/// Error returned by a Sled transaction /// Error returned by a Sled transaction
#[derive(Debug)] #[derive(Debug)]
pub enum SledTransactionError<T> { pub enum TransactionError<T> {
/// A failure returned by the API user that have aborted the transaction /// A failure returned by the API user that have aborted the transaction
Abort(T), Abort(T),
/// A storage related error /// A storage related error
Storage(io::Error), Storage(std::io::Error),
} }
impl<T: fmt::Display> fmt::Display for SledTransactionError<T> { impl<T: fmt::Display> fmt::Display for TransactionError<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
Self::Abort(e) => e.fmt(f), Self::Abort(e) => e.fmt(f),
@ -844,7 +857,7 @@ impl<T: fmt::Display> fmt::Display for SledTransactionError<T> {
} }
} }
impl<T: Error + 'static> Error for SledTransactionError<T> { impl<T: Error + 'static> Error for TransactionError<T> {
fn source(&self) -> Option<&(dyn Error + 'static)> { fn source(&self) -> Option<&(dyn Error + 'static)> {
match self { match self {
Self::Abort(e) => Some(e), Self::Abort(e) => Some(e),
@ -853,20 +866,20 @@ impl<T: Error + 'static> Error for SledTransactionError<T> {
} }
} }
impl<T> From<TransactionError<T>> for SledTransactionError<T> { impl<T> From<Sled2TransactionError<T>> for TransactionError<T> {
fn from(e: TransactionError<T>) -> Self { fn from(e: Sled2TransactionError<T>) -> Self {
match e { match e {
TransactionError::Abort(e) => Self::Abort(e), Sled2TransactionError::Abort(e) => Self::Abort(e),
TransactionError::Storage(e) => Self::Storage(e.into()), Sled2TransactionError::Storage(e) => Self::Storage(e.into()),
} }
} }
} }
impl<T: Into<io::Error>> From<SledTransactionError<T>> for io::Error { impl<T: Into<std::io::Error>> From<TransactionError<T>> for std::io::Error {
fn from(e: SledTransactionError<T>) -> Self { fn from(e: TransactionError<T>) -> Self {
match e { match e {
SledTransactionError::Abort(e) => e.into(), TransactionError::Abort(e) => e.into(),
SledTransactionError::Storage(e) => e, TransactionError::Storage(e) => e,
} }
} }
} }
@ -874,14 +887,14 @@ impl<T: Into<io::Error>> From<SledTransactionError<T>> for io::Error {
/// An error returned from the transaction methods. /// An error returned from the transaction methods.
/// Should be returned as it is /// Should be returned as it is
#[derive(Debug)] #[derive(Debug)]
pub enum SledUnabortableTransactionError { pub enum UnabortableTransactionError {
#[doc(hidden)] #[doc(hidden)]
Conflict, Conflict,
/// A regular error /// A regular error
Storage(io::Error), Storage(std::io::Error),
} }
impl fmt::Display for SledUnabortableTransactionError { impl fmt::Display for UnabortableTransactionError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
Self::Conflict => write!(f, "Transaction conflict"), Self::Conflict => write!(f, "Transaction conflict"),
@ -890,7 +903,7 @@ impl fmt::Display for SledUnabortableTransactionError {
} }
} }
impl Error for SledUnabortableTransactionError { impl Error for UnabortableTransactionError {
fn source(&self) -> Option<&(dyn Error + 'static)> { fn source(&self) -> Option<&(dyn Error + 'static)> {
match self { match self {
Self::Storage(e) => Some(e), Self::Storage(e) => Some(e),
@ -899,17 +912,17 @@ impl Error for SledUnabortableTransactionError {
} }
} }
impl From<SledUnabortableTransactionError> for EvaluationError { impl From<UnabortableTransactionError> for EvaluationError {
fn from(e: SledUnabortableTransactionError) -> Self { fn from(e: UnabortableTransactionError) -> Self {
match e { match e {
SledUnabortableTransactionError::Storage(e) => Self::Io(e), UnabortableTransactionError::Storage(e) => Self::Io(e),
SledUnabortableTransactionError::Conflict => Self::Conflict, UnabortableTransactionError::Conflict => Self::Conflict,
} }
} }
} }
impl From<StoreOrParseError<SledUnabortableTransactionError>> for SledUnabortableTransactionError { impl From<StoreOrParseError<UnabortableTransactionError>> for UnabortableTransactionError {
fn from(e: StoreOrParseError<SledUnabortableTransactionError>) -> Self { fn from(e: StoreOrParseError<UnabortableTransactionError>) -> Self {
match e { match e {
StoreOrParseError::Store(e) => e, StoreOrParseError::Store(e) => e,
StoreOrParseError::Parse(e) => Self::Storage(e), StoreOrParseError::Parse(e) => Self::Storage(e),
@ -917,27 +930,27 @@ impl From<StoreOrParseError<SledUnabortableTransactionError>> for SledUnabortabl
} }
} }
impl From<UnabortableTransactionError> for SledUnabortableTransactionError { impl From<Sled2UnabortableTransactionError> for UnabortableTransactionError {
fn from(e: UnabortableTransactionError) -> Self { fn from(e: Sled2UnabortableTransactionError) -> Self {
match e { match e {
UnabortableTransactionError::Storage(e) => Self::Storage(e.into()), Sled2UnabortableTransactionError::Storage(e) => Self::Storage(e.into()),
UnabortableTransactionError::Conflict => Self::Conflict, Sled2UnabortableTransactionError::Conflict => Self::Conflict,
} }
} }
} }
/// An error returned from the transaction closure /// An error returned from the transaction closure
#[derive(Debug)] #[derive(Debug)]
pub enum SledConflictableTransactionError<T> { pub enum ConflictableTransactionError<T> {
/// A failure returned by the user that will abort the transaction /// A failure returned by the user that will abort the transaction
Abort(T), Abort(T),
#[doc(hidden)] #[doc(hidden)]
Conflict, Conflict,
/// A storage related error /// A storage related error
Storage(io::Error), Storage(std::io::Error),
} }
impl<T: fmt::Display> fmt::Display for SledConflictableTransactionError<T> { impl<T: fmt::Display> fmt::Display for ConflictableTransactionError<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
Self::Conflict => write!(f, "Transaction conflict"), Self::Conflict => write!(f, "Transaction conflict"),
@ -947,7 +960,7 @@ impl<T: fmt::Display> fmt::Display for SledConflictableTransactionError<T> {
} }
} }
impl<T: Error + 'static> Error for SledConflictableTransactionError<T> { impl<T: Error + 'static> Error for ConflictableTransactionError<T> {
fn source(&self) -> Option<&(dyn Error + 'static)> { fn source(&self) -> Option<&(dyn Error + 'static)> {
match self { match self {
Self::Abort(e) => Some(e), Self::Abort(e) => Some(e),
@ -957,37 +970,37 @@ impl<T: Error + 'static> Error for SledConflictableTransactionError<T> {
} }
} }
impl<T> From<SledUnabortableTransactionError> for SledConflictableTransactionError<T> { impl<T> From<UnabortableTransactionError> for ConflictableTransactionError<T> {
fn from(e: SledUnabortableTransactionError) -> Self { fn from(e: UnabortableTransactionError) -> Self {
match e { match e {
SledUnabortableTransactionError::Storage(e) => Self::Storage(e), UnabortableTransactionError::Storage(e) => Self::Storage(e),
SledUnabortableTransactionError::Conflict => Self::Conflict, UnabortableTransactionError::Conflict => Self::Conflict,
} }
} }
} }
impl<T> From<SledConflictableTransactionError<T>> for ConflictableTransactionError<T> { impl<T> From<ConflictableTransactionError<T>> for Sled2ConflictableTransactionError<T> {
fn from(e: SledConflictableTransactionError<T>) -> Self { fn from(e: ConflictableTransactionError<T>) -> Self {
match e { match e {
SledConflictableTransactionError::Abort(e) => ConflictableTransactionError::Abort(e), ConflictableTransactionError::Abort(e) => Sled2ConflictableTransactionError::Abort(e),
SledConflictableTransactionError::Conflict => ConflictableTransactionError::Conflict, ConflictableTransactionError::Conflict => Sled2ConflictableTransactionError::Conflict,
SledConflictableTransactionError::Storage(e) => { ConflictableTransactionError::Storage(e) => {
ConflictableTransactionError::Storage(e.into()) Sled2ConflictableTransactionError::Storage(e.into())
} }
} }
} }
} }
impl StrEncodingAware for Storage { impl StrEncodingAware for Storage {
type Error = io::Error; type Error = std::io::Error;
} }
impl StrLookup for Storage { impl StrLookup for Storage {
fn get_str(&self, id: StrHash) -> Result<Option<String>, io::Error> { fn get_str(&self, id: StrHash) -> Result<Option<String>, std::io::Error> {
self.get_str(id) self.get_str(id)
} }
fn get_str_id(&self, value: &str) -> Result<Option<StrHash>, io::Error> { fn get_str_id(&self, value: &str) -> Result<Option<StrHash>, std::io::Error> {
let key = StrHash::new(value); let key = StrHash::new(value);
Ok(if self.contains_str(key)? { Ok(if self.contains_str(key)? {
Some(key) Some(key)
@ -998,7 +1011,7 @@ impl StrLookup for Storage {
} }
impl StrContainer for Storage { impl StrContainer for Storage {
fn insert_str(&self, value: &str) -> Result<StrHash, io::Error> { fn insert_str(&self, value: &str) -> Result<StrHash, std::io::Error> {
let key = StrHash::new(value); let key = StrHash::new(value);
self.insert_str(key, value)?; self.insert_str(key, value)?;
Ok(key) Ok(key)
@ -1006,15 +1019,15 @@ impl StrContainer for Storage {
} }
impl<'a> StrEncodingAware for StorageTransaction<'a> { impl<'a> StrEncodingAware for StorageTransaction<'a> {
type Error = SledUnabortableTransactionError; type Error = UnabortableTransactionError;
} }
impl<'a> StrLookup for StorageTransaction<'a> { impl<'a> StrLookup for StorageTransaction<'a> {
fn get_str(&self, id: StrHash) -> Result<Option<String>, SledUnabortableTransactionError> { fn get_str(&self, id: StrHash) -> Result<Option<String>, UnabortableTransactionError> {
self.get_str(id) self.get_str(id)
} }
fn get_str_id(&self, value: &str) -> Result<Option<StrHash>, SledUnabortableTransactionError> { fn get_str_id(&self, value: &str) -> Result<Option<StrHash>, UnabortableTransactionError> {
let key = StrHash::new(value); let key = StrHash::new(value);
Ok(if self.contains_str(key)? { Ok(if self.contains_str(key)? {
Some(key) Some(key)
@ -1025,7 +1038,7 @@ impl<'a> StrLookup for StorageTransaction<'a> {
} }
impl<'a> StrContainer for StorageTransaction<'a> { impl<'a> StrContainer for StorageTransaction<'a> {
fn insert_str(&self, value: &str) -> Result<StrHash, SledUnabortableTransactionError> { fn insert_str(&self, value: &str) -> Result<StrHash, UnabortableTransactionError> {
let key = StrHash::new(value); let key = StrHash::new(value);
self.insert_str(key, value)?; self.insert_str(key, value)?;
Ok(key) Ok(key)

@ -4,7 +4,7 @@ use crate::error::invalid_data_error;
use crate::model::xsd::*; use crate::model::xsd::*;
use crate::model::*; use crate::model::*;
use crate::sparql::EvaluationError; use crate::sparql::EvaluationError;
use crate::store::small_string::SmallString; use crate::storage::small_string::SmallString;
use rand::random; use rand::random;
use rio_api::model as rio; use rio_api::model as rio;
use siphasher::sip128::{Hasher128, SipHasher24}; use siphasher::sip128::{Hasher128, SipHasher24};

@ -1,4 +1,33 @@
//! Store based on the [Sled](https://sled.rs/) key-value database. //! API to access an on-on disk [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset).
//!
//! Usage example:
//! ```
//! use oxigraph::store::Store;
//! use oxigraph::sparql::QueryResults;
//! use oxigraph::model::*;
//! # use std::fs::remove_dir_all;
//!
//! # {
//! let store = Store::open("example.db")?;
//!
//! // insertion
//! let ex = NamedNode::new("http://example.com")?;
//! let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), None);
//! store.insert(&quad)?;
//!
//! // quad filter
//! let results: Result<Vec<Quad>,_> = store.quads_for_pattern(None, None, None, None).collect();
//! assert_eq!(vec![quad], results?);
//!
//! // SPARQL query
//! if let QueryResults::Solutions(mut solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }")? {
//! assert_eq!(solutions.next().unwrap()?.get("s"), Some(&ex.into()));
//! };
//! #
//! # };
//! # remove_dir_all("example.db")?;
//! # Result::<_,Box<dyn std::error::Error>>::Ok(())
//! ```
use std::convert::TryInto; use std::convert::TryInto;
use std::io::{BufRead, Write}; use std::io::{BufRead, Write};
@ -12,30 +41,33 @@ use crate::sparql::{
evaluate_query, evaluate_update, EvaluationError, Query, QueryOptions, QueryResults, Update, evaluate_query, evaluate_update, EvaluationError, Query, QueryOptions, QueryResults, Update,
UpdateOptions, UpdateOptions,
}; };
use crate::store::io::{dump_dataset, dump_graph, load_dataset, load_graph}; use crate::storage::io::{dump_dataset, dump_graph, load_dataset, load_graph};
use crate::store::numeric_encoder::{ use crate::storage::numeric_encoder::{
Decoder, EncodedTerm, ReadEncoder, StrContainer, StrEncodingAware, StrHash, StrLookup, Decoder, EncodedTerm, ReadEncoder, StrContainer, StrEncodingAware, StrHash, StrLookup,
WriteEncoder, WriteEncoder,
}; };
use crate::store::storage::*; pub use crate::storage::ConflictableTransactionError;
pub use crate::store::storage::{ pub use crate::storage::TransactionError;
SledConflictableTransactionError, SledTransactionError, SledUnabortableTransactionError, pub use crate::storage::UnabortableTransactionError;
use crate::storage::{
ChainedDecodingQuadIterator, DecodingGraphIterator, Storage, StorageTransaction,
}; };
/// Store based on the [Sled](https://sled.rs/) key-value database. /// An on-on disk [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset).
/// It encodes a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) and allows to query it using SPARQL. /// Allows to query and update it using SPARQL.
/// It is based on the [Sled](https://sled.rs/) key-value database.
/// ///
/// Warning: Sled is not stable yet and might break its storage format. /// Warning: Sled is not stable yet and might break its storage format.
/// ///
/// Usage example: /// Usage example:
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::Store;
/// use oxigraph::sparql::QueryResults; /// use oxigraph::sparql::QueryResults;
/// use oxigraph::model::*; /// use oxigraph::model::*;
/// # use std::fs::remove_dir_all; /// # use std::fs::remove_dir_all;
/// ///
/// # { /// # {
/// let store = SledStore::open("example.db")?; /// let store = Store::open("example.db")?;
/// ///
/// // insertion /// // insertion
/// let ex = NamedNode::new("http://example.com")?; /// let ex = NamedNode::new("http://example.com")?;
@ -56,21 +88,21 @@ pub use crate::store::storage::{
/// # Result::<_,Box<dyn std::error::Error>>::Ok(()) /// # Result::<_,Box<dyn std::error::Error>>::Ok(())
/// ``` /// ```
#[derive(Clone)] #[derive(Clone)]
pub struct SledStore { pub struct Store {
storage: Storage, storage: Storage,
} }
//TODO: indexes for the default graph and indexes for the named graphs (no more Optional and space saving) //TODO: indexes for the default graph and indexes for the named graphs (no more Optional and space saving)
impl SledStore { impl Store {
/// Creates a temporary [`SledStore`]() that will be deleted after drop. /// Creates a temporary [`Store`]() that will be deleted after drop.
pub fn new() -> Result<Self, io::Error> { pub fn new() -> Result<Self, io::Error> {
Ok(Self { Ok(Self {
storage: Storage::new()?, storage: Storage::new()?,
}) })
} }
/// Opens a [`SledStore`]() and creates it if it does not exist yet. /// Opens a [`Store`]() and creates it if it does not exist yet.
pub fn open(path: impl AsRef<Path>) -> Result<Self, io::Error> { pub fn open(path: impl AsRef<Path>) -> Result<Self, io::Error> {
Ok(Self { Ok(Self {
storage: Storage::open(path.as_ref())?, storage: Storage::open(path.as_ref())?,
@ -81,11 +113,11 @@ impl SledStore {
/// ///
/// Usage example: /// Usage example:
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::Store;
/// use oxigraph::model::*; /// use oxigraph::model::*;
/// use oxigraph::sparql::QueryResults; /// use oxigraph::sparql::QueryResults;
/// ///
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// ///
/// // insertions /// // insertions
/// let ex = NamedNodeRef::new("http://example.com")?; /// let ex = NamedNodeRef::new("http://example.com")?;
@ -117,10 +149,10 @@ impl SledStore {
/// ///
/// Usage example: /// Usage example:
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::Store;
/// use oxigraph::model::*; /// use oxigraph::model::*;
/// ///
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// ///
/// // insertion /// // insertion
/// let ex = NamedNode::new("http://example.com")?; /// let ex = NamedNode::new("http://example.com")?;
@ -138,8 +170,8 @@ impl SledStore {
predicate: Option<NamedNodeRef<'_>>, predicate: Option<NamedNodeRef<'_>>,
object: Option<TermRef<'_>>, object: Option<TermRef<'_>>,
graph_name: Option<GraphNameRef<'_>>, graph_name: Option<GraphNameRef<'_>>,
) -> SledQuadIter { ) -> QuadIter {
SledQuadIter { QuadIter {
inner: match self.get_encoded_quad_pattern(subject, predicate, object, graph_name) { inner: match self.get_encoded_quad_pattern(subject, predicate, object, graph_name) {
Ok(Some((subject, predicate, object, graph_name))) => QuadIterInner::Quads { Ok(Some((subject, predicate, object, graph_name))) => QuadIterInner::Quads {
iter: self iter: self
@ -209,7 +241,7 @@ impl SledStore {
} }
/// Returns all the quads contained in the store /// Returns all the quads contained in the store
pub fn iter(&self) -> SledQuadIter { pub fn iter(&self) -> QuadIter {
self.quads_for_pattern(None, None, None, None) self.quads_for_pattern(None, None, None, None)
} }
@ -241,10 +273,10 @@ impl SledStore {
/// ///
/// Usage example: /// Usage example:
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::Store;
/// use oxigraph::model::*; /// use oxigraph::model::*;
/// ///
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// ///
/// // insertion /// // insertion
/// store.update("INSERT DATA { <http://example.com> <http://example.com> <http://example.com> }")?; /// store.update("INSERT DATA { <http://example.com> <http://example.com> <http://example.com> }")?;
@ -281,12 +313,11 @@ impl SledStore {
/// ///
/// Usage example: /// Usage example:
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::{ConflictableTransactionError, Store};
/// use oxigraph::model::*; /// use oxigraph::model::*;
/// use oxigraph::store::sled::SledConflictableTransactionError;
/// use std::convert::Infallible; /// use std::convert::Infallible;
/// ///
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// ///
/// let ex = NamedNodeRef::new("http://example.com")?; /// let ex = NamedNodeRef::new("http://example.com")?;
/// let quad = QuadRef::new(ex, ex, ex, ex); /// let quad = QuadRef::new(ex, ex, ex, ex);
@ -294,7 +325,7 @@ impl SledStore {
/// // transaction /// // transaction
/// store.transaction(|transaction| { /// store.transaction(|transaction| {
/// transaction.insert(quad)?; /// transaction.insert(quad)?;
/// Ok(()) as Result<(),SledConflictableTransactionError<Infallible>> /// Ok(()) as Result<(),ConflictableTransactionError<Infallible>>
/// })?; /// })?;
/// ///
/// assert!(store.contains(quad)?); /// assert!(store.contains(quad)?);
@ -303,10 +334,10 @@ impl SledStore {
/// ``` /// ```
pub fn transaction<T, E>( pub fn transaction<T, E>(
&self, &self,
f: impl Fn(SledTransaction<'_>) -> Result<T, SledConflictableTransactionError<E>>, f: impl Fn(Transaction<'_>) -> Result<T, ConflictableTransactionError<E>>,
) -> Result<T, SledTransactionError<E>> { ) -> Result<T, TransactionError<E>> {
self.storage self.storage
.transaction(|storage| f(SledTransaction { storage })) .transaction(|storage| f(Transaction { storage }))
} }
/// Loads a graph file (i.e. triples) into the store /// Loads a graph file (i.e. triples) into the store
@ -314,15 +345,15 @@ impl SledStore {
/// Warning: This functions saves the triples in a not atomic way. /// Warning: This functions saves the triples in a not atomic way.
/// If the parsing fails in the middle of the file only a part of it may be written to the store. /// If the parsing fails in the middle of the file only a part of it may be written to the store.
/// It might leave the store in a bad state if a crash happens during a triple insertion. /// It might leave the store in a bad state if a crash happens during a triple insertion.
/// Use a (memory greedy) [transaction](SledStore::transaction()) if you do not want that. /// Use a (memory greedy) [transaction](Store::transaction()) if you do not want that.
/// ///
/// Usage example: /// Usage example:
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::Store;
/// use oxigraph::io::GraphFormat; /// use oxigraph::io::GraphFormat;
/// use oxigraph::model::*; /// use oxigraph::model::*;
/// ///
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// ///
/// // insertion /// // insertion
/// let file = b"<http://example.com> <http://example.com> <http://example.com> ."; /// let file = b"<http://example.com> <http://example.com> <http://example.com> .";
@ -359,15 +390,15 @@ impl SledStore {
/// Warning: This functions saves the triples in a not atomic way. /// Warning: This functions saves the triples in a not atomic way.
/// If the parsing fails in the middle of the file, only a part of it may be written to the store. /// If the parsing fails in the middle of the file, only a part of it may be written to the store.
/// It might leave the store in a bad state if a crash happens during a quad insertion. /// It might leave the store in a bad state if a crash happens during a quad insertion.
/// Use a (memory greedy) [transaction](SledStore::transaction()) if you do not want that. /// Use a (memory greedy) [transaction](Store::transaction()) if you do not want that.
/// ///
/// Usage example: /// Usage example:
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::Store;
/// use oxigraph::io::DatasetFormat; /// use oxigraph::io::DatasetFormat;
/// use oxigraph::model::*; /// use oxigraph::model::*;
/// ///
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// ///
/// // insertion /// // insertion
/// let file = b"<http://example.com> <http://example.com> <http://example.com> <http://example.com> ."; /// let file = b"<http://example.com> <http://example.com> <http://example.com> <http://example.com> .";
@ -398,7 +429,7 @@ impl SledStore {
/// ///
/// This method is optimized for performances and is not atomic. /// This method is optimized for performances and is not atomic.
/// It might leave the store in a bad state if a crash happens during the insertion. /// It might leave the store in a bad state if a crash happens during the insertion.
/// Use a (memory greedy) [transaction](SledStore::transaction()) if you do not want that. /// Use a (memory greedy) [transaction](Store::transaction()) if you do not want that.
pub fn insert<'a>(&self, quad: impl Into<QuadRef<'a>>) -> Result<bool, io::Error> { pub fn insert<'a>(&self, quad: impl Into<QuadRef<'a>>) -> Result<bool, io::Error> {
let quad = self.encode_quad(quad.into())?; let quad = self.encode_quad(quad.into())?;
self.storage.insert(&quad) self.storage.insert(&quad)
@ -410,7 +441,7 @@ impl SledStore {
/// ///
/// This method is optimized for performances and is not atomic. /// This method is optimized for performances and is not atomic.
/// It might leave the store in a bad state if a crash happens during the removal. /// It might leave the store in a bad state if a crash happens during the removal.
/// Use a (memory greedy) [transaction](SledStore::transaction()) if you do not want that. /// Use a (memory greedy) [transaction](Store::transaction()) if you do not want that.
pub fn remove<'a>(&self, quad: impl Into<QuadRef<'a>>) -> Result<bool, io::Error> { pub fn remove<'a>(&self, quad: impl Into<QuadRef<'a>>) -> Result<bool, io::Error> {
if let Some(quad) = self.get_encoded_quad(quad.into())? { if let Some(quad) = self.get_encoded_quad(quad.into())? {
self.storage.remove(&quad) self.storage.remove(&quad)
@ -423,13 +454,13 @@ impl SledStore {
/// ///
/// Usage example: /// Usage example:
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::Store;
/// use oxigraph::io::GraphFormat; /// use oxigraph::io::GraphFormat;
/// use oxigraph::model::GraphName; /// use oxigraph::model::GraphName;
/// ///
/// let file = "<http://example.com> <http://example.com> <http://example.com> .\n".as_bytes(); /// let file = "<http://example.com> <http://example.com> <http://example.com> .\n".as_bytes();
/// ///
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// store.load_graph(file, GraphFormat::NTriples, &GraphName::DefaultGraph, None)?; /// store.load_graph(file, GraphFormat::NTriples, &GraphName::DefaultGraph, None)?;
/// ///
/// let mut buffer = Vec::new(); /// let mut buffer = Vec::new();
@ -454,12 +485,12 @@ impl SledStore {
/// Dumps the store into a file. /// Dumps the store into a file.
/// ///
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::Store;
/// use oxigraph::io::DatasetFormat; /// use oxigraph::io::DatasetFormat;
/// ///
/// let file = "<http://example.com> <http://example.com> <http://example.com> <http://example.com> .\n".as_bytes(); /// let file = "<http://example.com> <http://example.com> <http://example.com> <http://example.com> .\n".as_bytes();
/// ///
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// store.load_dataset(file, DatasetFormat::NQuads, None)?; /// store.load_dataset(file, DatasetFormat::NQuads, None)?;
/// ///
/// let mut buffer = Vec::new(); /// let mut buffer = Vec::new();
@ -475,18 +506,18 @@ impl SledStore {
/// ///
/// Usage example: /// Usage example:
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::Store;
/// use oxigraph::model::{NamedNode, QuadRef, NamedOrBlankNode}; /// use oxigraph::model::{NamedNode, QuadRef, NamedOrBlankNode};
/// ///
/// let ex = NamedNode::new("http://example.com")?; /// let ex = NamedNode::new("http://example.com")?;
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// store.insert(QuadRef::new(&ex, &ex, &ex, &ex))?; /// store.insert(QuadRef::new(&ex, &ex, &ex, &ex))?;
/// store.insert(QuadRef::new(&ex, &ex, &ex, None))?; /// store.insert(QuadRef::new(&ex, &ex, &ex, None))?;
/// assert_eq!(vec![NamedOrBlankNode::from(ex)], store.named_graphs().collect::<Result<Vec<_>,_>>()?); /// assert_eq!(vec![NamedOrBlankNode::from(ex)], store.named_graphs().collect::<Result<Vec<_>,_>>()?);
/// # Result::<_,Box<dyn std::error::Error>>::Ok(()) /// # Result::<_,Box<dyn std::error::Error>>::Ok(())
/// ``` /// ```
pub fn named_graphs(&self) -> SledGraphNameIter { pub fn named_graphs(&self) -> GraphNameIter {
SledGraphNameIter { GraphNameIter {
iter: self.storage.named_graphs(), iter: self.storage.named_graphs(),
store: self.clone(), store: self.clone(),
} }
@ -496,11 +527,11 @@ impl SledStore {
/// ///
/// Usage example: /// Usage example:
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::Store;
/// use oxigraph::model::{NamedNode, QuadRef}; /// use oxigraph::model::{NamedNode, QuadRef};
/// ///
/// let ex = NamedNode::new("http://example.com")?; /// let ex = NamedNode::new("http://example.com")?;
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// store.insert(QuadRef::new(&ex, &ex, &ex, &ex))?; /// store.insert(QuadRef::new(&ex, &ex, &ex, &ex))?;
/// assert!(store.contains_named_graph(&ex)?); /// assert!(store.contains_named_graph(&ex)?);
/// # Result::<_,Box<dyn std::error::Error>>::Ok(()) /// # Result::<_,Box<dyn std::error::Error>>::Ok(())
@ -522,11 +553,11 @@ impl SledStore {
/// ///
/// Usage example: /// Usage example:
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::Store;
/// use oxigraph::model::NamedNodeRef; /// use oxigraph::model::NamedNodeRef;
/// ///
/// let ex = NamedNodeRef::new("http://example.com")?; /// let ex = NamedNodeRef::new("http://example.com")?;
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// store.insert_named_graph(ex)?; /// store.insert_named_graph(ex)?;
/// assert_eq!(store.named_graphs().count(), 1); /// assert_eq!(store.named_graphs().count(), 1);
/// # Result::<_,Box<dyn std::error::Error>>::Ok(()) /// # Result::<_,Box<dyn std::error::Error>>::Ok(())
@ -543,12 +574,12 @@ impl SledStore {
/// ///
/// Usage example: /// Usage example:
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::Store;
/// use oxigraph::model::{NamedNodeRef, QuadRef}; /// use oxigraph::model::{NamedNodeRef, QuadRef};
/// ///
/// let ex = NamedNodeRef::new("http://example.com")?; /// let ex = NamedNodeRef::new("http://example.com")?;
/// let quad = QuadRef::new(ex, ex, ex, ex); /// let quad = QuadRef::new(ex, ex, ex, ex);
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// store.insert(quad)?; /// store.insert(quad)?;
/// assert_eq!(1, store.len()); /// assert_eq!(1, store.len());
/// ///
@ -574,12 +605,12 @@ impl SledStore {
/// ///
/// Usage example: /// Usage example:
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::Store;
/// use oxigraph::model::{NamedNodeRef, QuadRef}; /// use oxigraph::model::{NamedNodeRef, QuadRef};
/// ///
/// let ex = NamedNodeRef::new("http://example.com")?; /// let ex = NamedNodeRef::new("http://example.com")?;
/// let quad = QuadRef::new(ex, ex, ex, ex); /// let quad = QuadRef::new(ex, ex, ex, ex);
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// store.insert(quad)?; /// store.insert(quad)?;
/// assert_eq!(1, store.len()); /// assert_eq!(1, store.len());
/// ///
@ -603,11 +634,11 @@ impl SledStore {
/// ///
/// Usage example: /// Usage example:
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::Store;
/// use oxigraph::model::{NamedNodeRef, QuadRef}; /// use oxigraph::model::{NamedNodeRef, QuadRef};
/// ///
/// let ex = NamedNodeRef::new("http://example.com")?; /// let ex = NamedNodeRef::new("http://example.com")?;
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// store.insert(QuadRef::new(ex, ex, ex, ex))?; /// store.insert(QuadRef::new(ex, ex, ex, ex))?;
/// store.insert(QuadRef::new(ex, ex, ex, None))?; /// store.insert(QuadRef::new(ex, ex, ex, None))?;
/// assert_eq!(2, store.len()); /// assert_eq!(2, store.len());
@ -621,7 +652,7 @@ impl SledStore {
} }
} }
impl fmt::Display for SledStore { impl fmt::Display for Store {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for t in self.iter() { for t in self.iter() {
writeln!(f, "{}", t.map_err(|_| fmt::Error)?)?; writeln!(f, "{}", t.map_err(|_| fmt::Error)?)?;
@ -630,11 +661,11 @@ impl fmt::Display for SledStore {
} }
} }
impl StrEncodingAware for SledStore { impl StrEncodingAware for Store {
type Error = io::Error; type Error = io::Error;
} }
impl StrLookup for SledStore { impl StrLookup for Store {
fn get_str(&self, id: StrHash) -> Result<Option<String>, io::Error> { fn get_str(&self, id: StrHash) -> Result<Option<String>, io::Error> {
self.storage.get_str(id) self.storage.get_str(id)
} }
@ -644,7 +675,7 @@ impl StrLookup for SledStore {
} }
} }
impl<'a> StrContainer for &'a SledStore { impl<'a> StrContainer for &'a Store {
fn insert_str(&self, value: &str) -> Result<StrHash, io::Error> { fn insert_str(&self, value: &str) -> Result<StrHash, io::Error> {
let key = StrHash::new(value); let key = StrHash::new(value);
self.storage.insert_str(key, value)?; self.storage.insert_str(key, value)?;
@ -652,12 +683,12 @@ impl<'a> StrContainer for &'a SledStore {
} }
} }
/// Allows inserting and deleting quads during an ACID transaction with the [`SledStore`]. /// Allows inserting and deleting quads during an ACID transaction with the [`Store`].
pub struct SledTransaction<'a> { pub struct Transaction<'a> {
storage: StorageTransaction<'a>, storage: StorageTransaction<'a>,
} }
impl SledTransaction<'_> { impl Transaction<'_> {
/// Loads a graph file (i.e. triples) into the store during the transaction. /// Loads a graph file (i.e. triples) into the store during the transaction.
/// ///
/// Warning: Because the load happens during a transaction, /// Warning: Because the load happens during a transaction,
@ -666,18 +697,18 @@ impl SledTransaction<'_> {
/// ///
/// Usage example: /// Usage example:
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::Store;
/// use oxigraph::io::GraphFormat; /// use oxigraph::io::GraphFormat;
/// use oxigraph::model::*; /// use oxigraph::model::*;
/// use oxigraph::store::sled::SledConflictableTransactionError; /// use oxigraph::store::ConflictableTransactionError;
/// ///
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// ///
/// // insertion /// // insertion
/// let file = b"<http://example.com> <http://example.com> <http://example.com> ."; /// let file = b"<http://example.com> <http://example.com> <http://example.com> .";
/// store.transaction(|transaction| { /// store.transaction(|transaction| {
/// transaction.load_graph(file.as_ref(), GraphFormat::NTriples, &GraphName::DefaultGraph, None)?; /// transaction.load_graph(file.as_ref(), GraphFormat::NTriples, &GraphName::DefaultGraph, None)?;
/// Ok(()) as Result<(),SledConflictableTransactionError<std::io::Error>> /// Ok(()) as Result<(),ConflictableTransactionError<std::io::Error>>
/// })?; /// })?;
/// ///
/// // we inspect the store content /// // we inspect the store content
@ -699,7 +730,7 @@ impl SledTransaction<'_> {
format: GraphFormat, format: GraphFormat,
to_graph_name: impl Into<GraphNameRef<'a>>, to_graph_name: impl Into<GraphNameRef<'a>>,
base_iri: Option<&str>, base_iri: Option<&str>,
) -> Result<(), SledUnabortableTransactionError> { ) -> Result<(), UnabortableTransactionError> {
load_graph( load_graph(
&self.storage, &self.storage,
reader, reader,
@ -718,18 +749,18 @@ impl SledTransaction<'_> {
/// ///
/// Usage example: /// Usage example:
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::store::{Store, ConflictableTransactionError};
/// use oxigraph::io::DatasetFormat; /// use oxigraph::io::DatasetFormat;
/// use oxigraph::model::*; /// use oxigraph::model::*;
/// use oxigraph::store::sled::SledConflictableTransactionError; /// use oxigraph::store::ConflictableTransactionError;
/// ///
/// let store = SledStore::new()?; /// let store = Store::new()?;
/// ///
/// // insertion /// // insertion
/// let file = b"<http://example.com> <http://example.com> <http://example.com> <http://example.com> ."; /// let file = b"<http://example.com> <http://example.com> <http://example.com> <http://example.com> .";
/// store.transaction(|transaction| { /// store.transaction(|transaction| {
/// transaction.load_dataset(file.as_ref(), DatasetFormat::NQuads, None)?; /// transaction.load_dataset(file.as_ref(), DatasetFormat::NQuads, None)?;
/// Ok(()) as Result<(),SledConflictableTransactionError<std::io::Error>> /// Ok(()) as Result<(),ConflictableTransactionError<std::io::Error>>
/// })?; /// })?;
/// ///
/// // we inspect the store content /// // we inspect the store content
@ -750,7 +781,7 @@ impl SledTransaction<'_> {
reader: impl BufRead, reader: impl BufRead,
format: DatasetFormat, format: DatasetFormat,
base_iri: Option<&str>, base_iri: Option<&str>,
) -> Result<(), SledUnabortableTransactionError> { ) -> Result<(), UnabortableTransactionError> {
Ok(load_dataset(&self.storage, reader, format, base_iri)?) Ok(load_dataset(&self.storage, reader, format, base_iri)?)
} }
@ -760,7 +791,7 @@ impl SledTransaction<'_> {
pub fn insert<'a>( pub fn insert<'a>(
&self, &self,
quad: impl Into<QuadRef<'a>>, quad: impl Into<QuadRef<'a>>,
) -> Result<bool, SledUnabortableTransactionError> { ) -> Result<bool, UnabortableTransactionError> {
let quad = self.encode_quad(quad.into())?; let quad = self.encode_quad(quad.into())?;
self.storage.insert(&quad) self.storage.insert(&quad)
} }
@ -771,7 +802,7 @@ impl SledTransaction<'_> {
pub fn remove<'a>( pub fn remove<'a>(
&self, &self,
quad: impl Into<QuadRef<'a>>, quad: impl Into<QuadRef<'a>>,
) -> Result<bool, SledUnabortableTransactionError> { ) -> Result<bool, UnabortableTransactionError> {
if let Some(quad) = self.get_encoded_quad(quad.into())? { if let Some(quad) = self.get_encoded_quad(quad.into())? {
self.storage.remove(&quad) self.storage.remove(&quad)
} else { } else {
@ -785,49 +816,49 @@ impl SledTransaction<'_> {
pub fn insert_named_graph<'a>( pub fn insert_named_graph<'a>(
&self, &self,
graph_name: impl Into<NamedOrBlankNodeRef<'a>>, graph_name: impl Into<NamedOrBlankNodeRef<'a>>,
) -> Result<bool, SledUnabortableTransactionError> { ) -> Result<bool, UnabortableTransactionError> {
let graph_name = self.encode_named_or_blank_node(graph_name.into())?; let graph_name = self.encode_named_or_blank_node(graph_name.into())?;
self.storage.insert_named_graph(graph_name) self.storage.insert_named_graph(graph_name)
} }
} }
impl<'a> StrEncodingAware for &'a SledTransaction<'a> { impl<'a> StrEncodingAware for &'a Transaction<'a> {
type Error = SledUnabortableTransactionError; type Error = UnabortableTransactionError;
} }
impl<'a> StrLookup for &'a SledTransaction<'a> { impl<'a> StrLookup for &'a Transaction<'a> {
fn get_str(&self, id: StrHash) -> Result<Option<String>, SledUnabortableTransactionError> { fn get_str(&self, id: StrHash) -> Result<Option<String>, UnabortableTransactionError> {
self.storage.get_str(id) self.storage.get_str(id)
} }
fn get_str_id(&self, value: &str) -> Result<Option<StrHash>, SledUnabortableTransactionError> { fn get_str_id(&self, value: &str) -> Result<Option<StrHash>, UnabortableTransactionError> {
self.storage.get_str_id(value) self.storage.get_str_id(value)
} }
} }
impl<'a> StrContainer for &'a SledTransaction<'a> { impl<'a> StrContainer for &'a Transaction<'a> {
fn insert_str(&self, value: &str) -> Result<StrHash, SledUnabortableTransactionError> { fn insert_str(&self, value: &str) -> Result<StrHash, UnabortableTransactionError> {
let key = StrHash::new(value); let key = StrHash::new(value);
self.storage.insert_str(key, value)?; self.storage.insert_str(key, value)?;
Ok(key) Ok(key)
} }
} }
/// An iterator returning the quads contained in a [`SledStore`]. /// An iterator returning the quads contained in a [`Store`].
pub struct SledQuadIter { pub struct QuadIter {
inner: QuadIterInner, inner: QuadIterInner,
} }
enum QuadIterInner { enum QuadIterInner {
Quads { Quads {
iter: ChainedDecodingQuadIterator, iter: ChainedDecodingQuadIterator,
store: SledStore, store: Store,
}, },
Error(Once<io::Error>), Error(Once<io::Error>),
Empty, Empty,
} }
impl Iterator for SledQuadIter { impl Iterator for QuadIter {
type Item = Result<Quad, io::Error>; type Item = Result<Quad, io::Error>;
fn next(&mut self) -> Option<Result<Quad, io::Error>> { fn next(&mut self) -> Option<Result<Quad, io::Error>> {
@ -842,13 +873,13 @@ impl Iterator for SledQuadIter {
} }
} }
/// An iterator returning the graph names contained in a [`SledStore`]. /// An iterator returning the graph names contained in a [`Store`].
pub struct SledGraphNameIter { pub struct GraphNameIter {
iter: DecodingGraphIterator, iter: DecodingGraphIterator,
store: SledStore, store: Store,
} }
impl Iterator for SledGraphNameIter { impl Iterator for GraphNameIter {
type Item = Result<NamedOrBlankNode, io::Error>; type Item = Result<NamedOrBlankNode, io::Error>;
fn next(&mut self) -> Option<Result<NamedOrBlankNode, io::Error>> { fn next(&mut self) -> Option<Result<NamedOrBlankNode, io::Error>> {
@ -910,12 +941,12 @@ fn store() -> Result<(), io::Error> {
named_quad.clone(), named_quad.clone(),
]; ];
let store = SledStore::new()?; let store = Store::new()?;
for t in &default_quads { for t in &default_quads {
assert!(store.insert(t)?); assert!(store.insert(t)?);
} }
let result: Result<_, SledTransactionError<io::Error>> = store.transaction(|t| { let result: Result<_, TransactionError<io::Error>> = store.transaction(|t| {
assert!(t.remove(&default_quad)?); assert!(t.remove(&default_quad)?);
assert_eq!(t.remove(&default_quad)?, false); assert_eq!(t.remove(&default_quad)?, false);
assert!(t.insert(&named_quad)?); assert!(t.insert(&named_quad)?);

@ -1,12 +0,0 @@
//! RDF [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) storage implementations.
pub use crate::store::sled::SledStore;
mod binary_encoder;
pub(crate) mod io;
pub(crate) mod numeric_encoder;
pub mod sled;
pub(crate) mod small_string;
#[cfg(feature = "sophia")]
mod sophia;
pub(crate) mod storage;

@ -1,8 +1,8 @@
use oxigraph::io::{DatasetFormat, GraphFormat}; use oxigraph::io::{DatasetFormat, GraphFormat};
use oxigraph::model::vocab::{rdf, xsd}; use oxigraph::model::vocab::{rdf, xsd};
use oxigraph::model::*; use oxigraph::model::*;
use oxigraph::store::sled::SledConflictableTransactionError; use oxigraph::store::ConflictableTransactionError;
use oxigraph::SledStore; use oxigraph::store::Store;
use std::io; use std::io;
use std::io::Cursor; use std::io::Cursor;
use std::process::Command; use std::process::Command;
@ -77,7 +77,7 @@ fn quads(graph_name: impl Into<GraphNameRef<'static>>) -> Vec<QuadRef<'static>>
#[test] #[test]
fn test_load_graph() -> io::Result<()> { fn test_load_graph() -> io::Result<()> {
let store = SledStore::new()?; let store = Store::new()?;
store.load_graph(Cursor::new(DATA), GraphFormat::Turtle, None, None)?; store.load_graph(Cursor::new(DATA), GraphFormat::Turtle, None, None)?;
for q in quads(GraphNameRef::DefaultGraph) { for q in quads(GraphNameRef::DefaultGraph) {
assert!(store.contains(q)?); assert!(store.contains(q)?);
@ -87,7 +87,7 @@ fn test_load_graph() -> io::Result<()> {
#[test] #[test]
fn test_load_dataset() -> io::Result<()> { fn test_load_dataset() -> io::Result<()> {
let store = SledStore::new()?; let store = Store::new()?;
store.load_dataset(Cursor::new(DATA), DatasetFormat::TriG, None)?; store.load_dataset(Cursor::new(DATA), DatasetFormat::TriG, None)?;
for q in quads(GraphNameRef::DefaultGraph) { for q in quads(GraphNameRef::DefaultGraph) {
assert!(store.contains(q)?); assert!(store.contains(q)?);
@ -97,7 +97,7 @@ fn test_load_dataset() -> io::Result<()> {
#[test] #[test]
fn test_dump_graph() -> io::Result<()> { fn test_dump_graph() -> io::Result<()> {
let store = SledStore::new()?; let store = Store::new()?;
for q in quads(GraphNameRef::DefaultGraph) { for q in quads(GraphNameRef::DefaultGraph) {
store.insert(q)?; store.insert(q)?;
} }
@ -113,7 +113,7 @@ fn test_dump_graph() -> io::Result<()> {
#[test] #[test]
fn test_dump_dataset() -> io::Result<()> { fn test_dump_dataset() -> io::Result<()> {
let store = SledStore::new()?; let store = Store::new()?;
for q in quads(GraphNameRef::DefaultGraph) { for q in quads(GraphNameRef::DefaultGraph) {
store.insert(q)?; store.insert(q)?;
} }
@ -129,10 +129,10 @@ fn test_dump_dataset() -> io::Result<()> {
#[test] #[test]
fn test_transaction_load_graph() -> io::Result<()> { fn test_transaction_load_graph() -> io::Result<()> {
let store = SledStore::new()?; let store = Store::new()?;
store.transaction(|t| { store.transaction(|t| {
t.load_graph(Cursor::new(DATA), GraphFormat::Turtle, None, None)?; t.load_graph(Cursor::new(DATA), GraphFormat::Turtle, None, None)?;
Ok(()) as Result<_, SledConflictableTransactionError<io::Error>> Ok(()) as Result<_, ConflictableTransactionError<io::Error>>
})?; })?;
for q in quads(GraphNameRef::DefaultGraph) { for q in quads(GraphNameRef::DefaultGraph) {
assert!(store.contains(q)?); assert!(store.contains(q)?);
@ -142,10 +142,10 @@ fn test_transaction_load_graph() -> io::Result<()> {
#[test] #[test]
fn test_transaction_load_dataset() -> io::Result<()> { fn test_transaction_load_dataset() -> io::Result<()> {
let store = SledStore::new()?; let store = Store::new()?;
store.transaction(|t| { store.transaction(|t| {
t.load_dataset(Cursor::new(DATA), DatasetFormat::TriG, None)?; t.load_dataset(Cursor::new(DATA), DatasetFormat::TriG, None)?;
Ok(()) as Result<_, SledConflictableTransactionError<io::Error>> Ok(()) as Result<_, ConflictableTransactionError<io::Error>>
})?; })?;
for q in quads(GraphNameRef::DefaultGraph) { for q in quads(GraphNameRef::DefaultGraph) {
assert!(store.contains(q)?); assert!(store.contains(q)?);
@ -156,7 +156,7 @@ fn test_transaction_load_dataset() -> io::Result<()> {
#[test] #[test]
fn test_backward_compatibility() -> io::Result<()> { fn test_backward_compatibility() -> io::Result<()> {
{ {
let store = SledStore::open("tests/sled_bc_data")?; let store = Store::open("tests/sled_bc_data")?;
for q in quads(GraphNameRef::DefaultGraph) { for q in quads(GraphNameRef::DefaultGraph) {
assert!(store.contains(q)?); assert!(store.contains(q)?);
} }

@ -3,7 +3,7 @@ use crate::model::*;
use crate::sparql::*; use crate::sparql::*;
use oxigraph::io::{DatasetFormat, GraphFormat}; use oxigraph::io::{DatasetFormat, GraphFormat};
use oxigraph::model::GraphNameRef; use oxigraph::model::GraphNameRef;
use oxigraph::store::sled::*; use oxigraph::store::{self, Store};
use pyo3::exceptions::PyValueError; use pyo3::exceptions::PyValueError;
use pyo3::prelude::{ use pyo3::prelude::{
pyclass, pymethods, pyproto, Py, PyAny, PyObject, PyRef, PyRefMut, PyResult, Python, pyclass, pymethods, pyproto, Py, PyAny, PyObject, PyRef, PyRefMut, PyResult, Python,
@ -31,7 +31,7 @@ use std::io::BufReader;
#[text_signature = "(path = None)"] #[text_signature = "(path = None)"]
#[derive(Clone)] #[derive(Clone)]
pub struct PyStore { pub struct PyStore {
inner: SledStore, inner: Store,
} }
#[pymethods] #[pymethods]
@ -40,9 +40,9 @@ impl PyStore {
fn new(path: Option<&str>) -> PyResult<Self> { fn new(path: Option<&str>) -> PyResult<Self> {
Ok(Self { Ok(Self {
inner: if let Some(path) = path { inner: if let Some(path) = path {
SledStore::open(path) Store::open(path)
} else { } else {
SledStore::new() Store::new()
} }
.map_err(map_io_err)?, .map_err(map_io_err)?,
}) })
@ -459,7 +459,7 @@ impl PyIterProtocol for PyStore {
#[pyclass(unsendable, module = "oxigraph")] #[pyclass(unsendable, module = "oxigraph")]
pub struct QuadIter { pub struct QuadIter {
inner: SledQuadIter, inner: store::QuadIter,
} }
#[pyproto] #[pyproto]
@ -478,7 +478,7 @@ impl PyIterProtocol for QuadIter {
#[pyclass(unsendable, module = "oxigraph")] #[pyclass(unsendable, module = "oxigraph")]
pub struct GraphNameIter { pub struct GraphNameIter {
inner: SledGraphNameIter, inner: store::GraphNameIter,
} }
#[pyproto] #[pyproto]

@ -23,7 +23,7 @@ use http_types::{
use oxigraph::io::{DatasetFormat, GraphFormat}; use oxigraph::io::{DatasetFormat, GraphFormat};
use oxigraph::model::{GraphName, GraphNameRef, NamedNode, NamedOrBlankNode}; use oxigraph::model::{GraphName, GraphNameRef, NamedNode, NamedOrBlankNode};
use oxigraph::sparql::{Query, QueryResults, QueryResultsFormat, Update}; use oxigraph::sparql::{Query, QueryResults, QueryResultsFormat, Update};
use oxigraph::SledStore as Store; use oxigraph::store::Store;
use oxiri::Iri; use oxiri::Iri;
use rand::random; use rand::random;
use std::io::BufReader; use std::io::BufReader;

@ -1,7 +1,7 @@
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use oxigraph::io::{DatasetFormat, GraphFormat}; use oxigraph::io::{DatasetFormat, GraphFormat};
use oxigraph::model::{Dataset, Graph, GraphNameRef}; use oxigraph::model::{Dataset, Graph, GraphNameRef};
use oxigraph::SledStore; use oxigraph::store::Store;
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader, Read}; use std::io::{BufRead, BufReader, Read};
use std::path::PathBuf; use std::path::PathBuf;
@ -41,7 +41,7 @@ pub fn read_file_to_string(url: &str) -> Result<String> {
pub fn load_to_store<'a>( pub fn load_to_store<'a>(
url: &str, url: &str,
store: &SledStore, store: &Store,
to_graph_name: impl Into<GraphNameRef<'a>>, to_graph_name: impl Into<GraphNameRef<'a>>,
) -> Result<()> { ) -> Result<()> {
if url.ends_with(".nt") { if url.ends_with(".nt") {

@ -7,7 +7,7 @@ use chrono::Utc;
use oxigraph::model::vocab::*; use oxigraph::model::vocab::*;
use oxigraph::model::*; use oxigraph::model::*;
use oxigraph::sparql::*; use oxigraph::sparql::*;
use oxigraph::SledStore; use oxigraph::store::Store;
use std::collections::HashMap; use std::collections::HashMap;
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
@ -70,7 +70,7 @@ fn evaluate_sparql_test(test: &Test) -> Result<()> {
} else if test.kind } else if test.kind
== "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#QueryEvaluationTest" == "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#QueryEvaluationTest"
{ {
let store = SledStore::new()?; let store = Store::new()?;
if let Some(data) = &test.data { if let Some(data) = &test.data {
load_to_store(data, &store, GraphNameRef::DefaultGraph)?; load_to_store(data, &store, GraphNameRef::DefaultGraph)?;
} }
@ -190,7 +190,7 @@ fn evaluate_sparql_test(test: &Test) -> Result<()> {
} else if test.kind } else if test.kind
== "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#UpdateEvaluationTest" == "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#UpdateEvaluationTest"
{ {
let store = SledStore::new()?; let store = Store::new()?;
if let Some(data) = &test.data { if let Some(data) = &test.data {
load_to_store(data, &store, &GraphName::DefaultGraph)?; load_to_store(data, &store, &GraphName::DefaultGraph)?;
} }
@ -198,7 +198,7 @@ fn evaluate_sparql_test(test: &Test) -> Result<()> {
load_to_store(value, &store, name)?; load_to_store(value, &store, name)?;
} }
let result_store = SledStore::new()?; let result_store = Store::new()?;
if let Some(data) = &test.result { if let Some(data) = &test.result {
load_to_store(data, &result_store, &GraphName::DefaultGraph)?; load_to_store(data, &result_store, &GraphName::DefaultGraph)?;
} }
@ -270,7 +270,7 @@ fn load_sparql_query_result(url: &str) -> Result<StaticQueryResults> {
#[derive(Clone)] #[derive(Clone)]
struct StaticServiceHandler { struct StaticServiceHandler {
services: Arc<HashMap<NamedNode, SledStore>>, services: Arc<HashMap<NamedNode, Store>>,
} }
impl StaticServiceHandler { impl StaticServiceHandler {
@ -281,7 +281,7 @@ impl StaticServiceHandler {
.iter() .iter()
.map(|(name, data)| { .map(|(name, data)| {
let name = NamedNode::new(name)?; let name = NamedNode::new(name)?;
let store = SledStore::new()?; let store = Store::new()?;
load_to_store(&data, &store, &GraphName::DefaultGraph)?; load_to_store(&data, &store, &GraphName::DefaultGraph)?;
Ok((name, store)) Ok((name, store))
}) })
@ -467,7 +467,7 @@ impl StaticQueryResults {
fn from_graph(graph: Graph) -> StaticQueryResults { fn from_graph(graph: Graph) -> StaticQueryResults {
// Hack to normalize literals // Hack to normalize literals
let store = SledStore::new().unwrap(); let store = Store::new().unwrap();
for t in graph.iter() { for t in graph.iter() {
store store
.insert(t.in_graph(GraphNameRef::DefaultGraph)) .insert(t.in_graph(GraphNameRef::DefaultGraph))

@ -7,7 +7,7 @@ use http_client::HttpClient;
use http_types::{headers, Method, Request, Result}; use http_types::{headers, Method, Request, Result};
use oxigraph::io::GraphFormat; use oxigraph::io::GraphFormat;
use oxigraph::model::NamedNodeRef; use oxigraph::model::NamedNodeRef;
use oxigraph::SledStore; use oxigraph::store::Store;
use serde_json::Value; use serde_json::Value;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::io::{BufReader, Cursor, Read}; use std::io::{BufReader, Cursor, Read};
@ -16,7 +16,7 @@ use std::time::Duration;
use url::{form_urlencoded, Url}; use url::{form_urlencoded, Url};
pub struct WikibaseLoader { pub struct WikibaseLoader {
store: SledStore, store: Store,
client: H1Client, client: H1Client,
api_url: Url, api_url: Url,
entity_data_url: Url, entity_data_url: Url,
@ -28,7 +28,7 @@ pub struct WikibaseLoader {
impl WikibaseLoader { impl WikibaseLoader {
pub fn new( pub fn new(
store: SledStore, store: Store,
api_url: &str, api_url: &str,
pages_base_url: &str, pages_base_url: &str,
namespaces: &[u32], namespaces: &[u32],

@ -23,7 +23,7 @@ use http_types::{
use oxigraph::io::GraphFormat; use oxigraph::io::GraphFormat;
use oxigraph::model::{GraphName, NamedNode, NamedOrBlankNode}; use oxigraph::model::{GraphName, NamedNode, NamedOrBlankNode};
use oxigraph::sparql::{Query, QueryResults, QueryResultsFormat}; use oxigraph::sparql::{Query, QueryResults, QueryResultsFormat};
use oxigraph::SledStore; use oxigraph::store::Store;
use std::str::FromStr; use std::str::FromStr;
use std::time::Duration; use std::time::Duration;
use url::form_urlencoded; use url::form_urlencoded;
@ -65,7 +65,7 @@ struct Args {
pub async fn main() -> Result<()> { pub async fn main() -> Result<()> {
let args: Args = argh::from_env(); let args: Args = argh::from_env();
let store = SledStore::open(args.file)?; let store = Store::open(args.file)?;
let mediawiki_api = args.mediawiki_api.clone(); let mediawiki_api = args.mediawiki_api.clone();
let mediawiki_base_url = args.mediawiki_base_url.clone(); let mediawiki_base_url = args.mediawiki_base_url.clone();
let namespaces = args let namespaces = args
@ -106,7 +106,7 @@ pub async fn main() -> Result<()> {
.await .await
} }
async fn handle_request(request: Request, store: SledStore) -> Result<Response> { async fn handle_request(request: Request, store: Store) -> Result<Response> {
Ok(match (request.url().path(), request.method()) { Ok(match (request.url().path(), request.method()) {
("/query", Method::Get) => { ("/query", Method::Get) => {
configure_and_evaluate_sparql_query(store, url_query(&request), None, request)? configure_and_evaluate_sparql_query(store, url_query(&request), None, request)?
@ -159,7 +159,7 @@ fn url_query(request: &Request) -> Vec<u8> {
} }
fn configure_and_evaluate_sparql_query( fn configure_and_evaluate_sparql_query(
store: SledStore, store: Store,
encoded: Vec<u8>, encoded: Vec<u8>,
mut query: Option<String>, mut query: Option<String>,
request: Request, request: Request,
@ -187,7 +187,7 @@ fn configure_and_evaluate_sparql_query(
} }
fn evaluate_sparql_query( fn evaluate_sparql_query(
store: SledStore, store: Store,
query: String, query: String,
default_graph_uris: Vec<String>, default_graph_uris: Vec<String>,
named_graph_uris: Vec<String>, named_graph_uris: Vec<String>,

Loading…
Cancel
Save