diff --git a/lib/README.md b/lib/README.md index 619c4999..e54ad608 100644 --- a/lib/README.md +++ b/lib/README.md @@ -29,11 +29,11 @@ A preliminary benchmark [is provided](../bench/README.md). Usage example: ```rust -use oxigraph::SledStore; -use oxigraph::model::*; +use oxigraph::store::Store; use oxigraph::sparql::QueryResults; +use oxigraph::model::*; -let store = SledStore::new()?; +let store = Store::open("example.db")?; // insertion 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)?; // quad filter -let results = store.quads_for_pattern(Some(ex.as_ref().into()), None, None, None).collect::,_>>()?; -assert_eq!(vec![quad], results); +let results: Result,_> = 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())); -} +if let QueryResults::Solutions(mut solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }")? { +assert_eq!(solutions.next().unwrap()?.get("s"), Some(&ex.into())); +}; ``` ## License diff --git a/lib/benches/store.rs b/lib/benches/store.rs index e388c0ed..f283fde9 100644 --- a/lib/benches/store.rs +++ b/lib/benches/store.rs @@ -1,6 +1,6 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; use oxigraph::model::{Dataset, Graph, NamedNode, Quad, Triple}; -use oxigraph::SledStore; +use oxigraph::store::Store; use rand::random; use std::iter::FromIterator; @@ -54,7 +54,7 @@ fn sled_load_bench(c: &mut Criterion) { let quads = create_quads(*size); group.bench_function(BenchmarkId::from_parameter(size), |b| { b.iter(|| { - let store = SledStore::new().unwrap(); + let store = Store::new().unwrap(); for quad in &quads { store.insert(quad).unwrap(); } diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 6bd4af39..357c8c8b 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -9,12 +9,15 @@ //! //! 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::sparql::QueryResults; //! -//! let store = SledStore::new()?; +//! let store = Store::new()?; //! //! // insertion //! let ex = NamedNode::new("http://example.com")?; @@ -112,7 +115,8 @@ mod error; pub mod io; pub mod model; +#[cfg(feature = "sophia")] +mod sophia; pub mod sparql; +mod storage; pub mod store; - -pub use crate::store::sled::SledStore; diff --git a/lib/src/store/sophia.rs b/lib/src/sophia.rs similarity index 97% rename from lib/src/store/sophia.rs rename to lib/src/sophia.rs index 287e0eb2..d0558918 100644 --- a/lib/src/store/sophia.rs +++ b/lib/src/sophia.rs @@ -5,7 +5,7 @@ use crate::model::{ TermRef, }; use crate::sparql::{EvaluationError, QueryResults}; -use crate::store::SledStore; +use crate::store::Store; use sophia_api::dataset::{ CollectibleDataset, DQuadSource, DResultTermSet, DTerm, Dataset, MDResult, MutableDataset, }; @@ -20,7 +20,7 @@ use std::iter::empty; type SophiaQuad = ([Term; 3], Option); type StreamedSophiaQuad<'a> = StreamedQuad<'a, ByValue>; -impl Dataset for SledStore { +impl Dataset for Store { type Quad = ByValue; type Error = Error; @@ -373,7 +373,7 @@ impl Dataset for SledStore { } } -impl MutableDataset for SledStore { +impl MutableDataset for Store { type MutationError = Error; fn insert( &mut self, @@ -397,7 +397,7 @@ impl MutableDataset for SledStore { Some(quad) => quad, None => return Ok(false), }; - SledStore::insert(self, quadref).map(|_| true) + Store::insert(self, quadref).map(|_| true) } fn remove( @@ -422,13 +422,13 @@ impl MutableDataset for SledStore { Some(quad) => quad, 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(quads: QS) -> StreamResult { - 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)?; Ok(d) } @@ -576,7 +576,7 @@ where /// # Precondition /// + the query must be a SELECT query with a single selected variable /// + it must not produce NULL results -fn sparql_to_hashset(store: &SledStore, sparql: &str) -> Result, Error> { +fn sparql_to_hashset(store: &Store, sparql: &str) -> Result, Error> { if let QueryResults::Solutions(solutions) = store.query(sparql).map_err(io_err_map)? { solutions .map(|r| r.map(|v| v.get(0).unwrap().clone())) @@ -588,4 +588,4 @@ fn sparql_to_hashset(store: &SledStore, sparql: &str) -> Result, E } #[cfg(test)] -sophia_api::test_dataset_impl!(test, SledStore, false, false); +sophia_api::test_dataset_impl!(test, Store, false, false); diff --git a/lib/src/sparql/dataset.rs b/lib/src/sparql/dataset.rs index f8e7e3c1..f54cc2f9 100644 --- a/lib/src/sparql/dataset.rs +++ b/lib/src/sparql/dataset.rs @@ -1,9 +1,9 @@ use crate::sparql::algebra::QueryDataset; use crate::sparql::EvaluationError; -use crate::store::numeric_encoder::{ +use crate::storage::numeric_encoder::{ EncodedQuad, EncodedTerm, ReadEncoder, StrContainer, StrEncodingAware, StrHash, StrLookup, }; -use crate::store::storage::Storage; +use crate::storage::Storage; use std::cell::RefCell; use std::collections::HashMap; use std::iter::empty; diff --git a/lib/src/sparql/error.rs b/lib/src/sparql/error.rs index f7e489a3..3c84f755 100644 --- a/lib/src/sparql/error.rs +++ b/lib/src/sparql/error.rs @@ -1,6 +1,6 @@ use crate::error::invalid_data_error; use crate::sparql::ParseError; -use crate::store::numeric_encoder::DecoderError; +use crate::storage::numeric_encoder::DecoderError; use std::convert::Infallible; use std::error; use std::fmt; diff --git a/lib/src/sparql/eval.rs b/lib/src/sparql/eval.rs index 71202780..67b853fc 100644 --- a/lib/src/sparql/eval.rs +++ b/lib/src/sparql/eval.rs @@ -8,8 +8,8 @@ use crate::sparql::error::EvaluationError; use crate::sparql::model::*; use crate::sparql::plan::*; use crate::sparql::service::ServiceHandler; -use crate::store::numeric_encoder::*; -use crate::store::small_string::SmallString; +use crate::storage::numeric_encoder::*; +use crate::storage::small_string::SmallString; use digest::Digest; use md5::Md5; use oxilangtag::LanguageTag; diff --git a/lib/src/sparql/mod.rs b/lib/src/sparql/mod.rs index c84136f4..e551aed2 100644 --- a/lib/src/sparql/mod.rs +++ b/lib/src/sparql/mod.rs @@ -1,6 +1,6 @@ //! [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 csv_results; @@ -30,7 +30,7 @@ use crate::sparql::plan_builder::PlanBuilder; pub use crate::sparql::service::ServiceHandler; use crate::sparql::service::{EmptyServiceHandler, ErrorConversionServiceHandler}; use crate::sparql::update::SimpleUpdateEvaluator; -use crate::store::storage::Storage; +use crate::storage::Storage; pub use spargebra::ParseError; use std::convert::TryInto; use std::rc::Rc; diff --git a/lib/src/sparql/model.rs b/lib/src/sparql/model.rs index 6bef3b27..0dac7437 100644 --- a/lib/src/sparql/model.rs +++ b/lib/src/sparql/model.rs @@ -44,11 +44,11 @@ impl QueryResults { /// This method fails if it is called on the `Graph` results /// /// ``` - /// use oxigraph::SledStore; + /// use oxigraph::store::Store; /// use oxigraph::model::*; /// use oxigraph::sparql::QueryResultsFormat; /// - /// let store = SledStore::new()?; + /// let store = Store::new()?; /// let ex = NamedNodeRef::new("http://example.com")?; /// 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 /// /// ``` - /// use oxigraph::SledStore; + /// use oxigraph::store::Store; /// use oxigraph::io::GraphFormat; /// use oxigraph::model::*; /// use std::io::Cursor; /// /// let graph = " .\n".as_bytes(); /// - /// let store = SledStore::new()?; + /// let store = Store::new()?; /// store.load_graph(Cursor::new(graph), GraphFormat::NTriples, &GraphName::DefaultGraph, None)?; /// /// let mut results = Vec::new(); @@ -216,10 +216,10 @@ impl QueryResultsFormat { /// An iterator over [`QuerySolution`]s /// /// ``` -/// use oxigraph::SledStore; +/// use oxigraph::store::Store; /// 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 }")? { /// for solution in solutions { /// println!("{:?}", solution?.get("s")); @@ -243,10 +243,10 @@ impl QuerySolutionIter { /// The variables used in the solutions /// /// ``` - /// use oxigraph::SledStore; + /// use oxigraph::store::Store; /// 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 }")? { /// 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 /// /// ``` -/// use oxigraph::SledStore; +/// use oxigraph::store::Store; /// use oxigraph::sparql::QueryResults; /// -/// let store = SledStore::new()?; +/// let store = Store::new()?; /// if let QueryResults::Graph(triples) = store.query("CONSTRUCT WHERE { ?s ?p ?o }")? { /// for triple in triples { /// println!("{}", triple?); diff --git a/lib/src/sparql/plan.rs b/lib/src/sparql/plan.rs index f3fef050..adbecb08 100644 --- a/lib/src/sparql/plan.rs +++ b/lib/src/sparql/plan.rs @@ -1,5 +1,5 @@ use crate::sparql::model::Variable; -use crate::store::numeric_encoder::EncodedTerm; +use crate::storage::numeric_encoder::EncodedTerm; use spargebra::algebra::GraphPattern; use std::collections::BTreeSet; use std::rc::Rc; diff --git a/lib/src/sparql/plan_builder.rs b/lib/src/sparql/plan_builder.rs index 66e4fc4a..873db541 100644 --- a/lib/src/sparql/plan_builder.rs +++ b/lib/src/sparql/plan_builder.rs @@ -3,7 +3,7 @@ use crate::sparql::dataset::DatasetView; use crate::sparql::error::EvaluationError; use crate::sparql::model::Variable as OxVariable; use crate::sparql::plan::*; -use crate::store::numeric_encoder::{EncodedTerm, WriteEncoder}; +use crate::storage::numeric_encoder::{EncodedTerm, WriteEncoder}; use rand::random; use spargebra::algebra::*; use spargebra::term::*; diff --git a/lib/src/sparql/service.rs b/lib/src/sparql/service.rs index e643ffa6..58a75f95 100644 --- a/lib/src/sparql/service.rs +++ b/lib/src/sparql/service.rs @@ -15,12 +15,12 @@ use std::error::Error; /// before evaluating a SPARQL query that uses SERVICE calls. /// /// ``` -/// use oxigraph::SledStore; +/// use oxigraph::store::Store; /// use oxigraph::model::*; /// use oxigraph::sparql::{QueryOptions, QueryResults, ServiceHandler, Query, EvaluationError}; /// /// struct TestServiceHandler { -/// store: SledStore +/// store: Store /// } /// /// impl ServiceHandler for TestServiceHandler { @@ -35,9 +35,9 @@ use std::error::Error; /// } /// } /// -/// let store = SledStore::new()?; +/// let store = Store::new()?; /// let service = TestServiceHandler { -/// store: SledStore::new()? +/// store: Store::new()? /// }; /// let ex = NamedNodeRef::new("http://example.com")?; /// service.store.insert(QuadRef::new(ex, ex, ex, GraphNameRef::DefaultGraph))?; diff --git a/lib/src/sparql/update.rs b/lib/src/sparql/update.rs index 41678a5f..b47bc079 100644 --- a/lib/src/sparql/update.rs +++ b/lib/src/sparql/update.rs @@ -8,11 +8,11 @@ use crate::sparql::http::Client; use crate::sparql::plan::EncodedTuple; use crate::sparql::plan_builder::PlanBuilder; use crate::sparql::{EvaluationError, UpdateOptions}; -use crate::store::io::load_graph; -use crate::store::numeric_encoder::{ +use crate::storage::io::load_graph; +use crate::storage::numeric_encoder::{ EncodedQuad, EncodedTerm, ReadEncoder, StrLookup, WriteEncoder, }; -use crate::store::storage::Storage; +use crate::storage::Storage; use http::header::{ACCEPT, CONTENT_TYPE, USER_AGENT}; use http::{Method, Request, StatusCode}; use oxiri::Iri; diff --git a/lib/src/store/binary_encoder.rs b/lib/src/storage/binary_encoder.rs similarity index 99% rename from lib/src/store/binary_encoder.rs rename to lib/src/storage/binary_encoder.rs index 3b5abfe1..1ddb729c 100644 --- a/lib/src/store/binary_encoder.rs +++ b/lib/src/storage/binary_encoder.rs @@ -1,7 +1,7 @@ use crate::error::invalid_data_error; use crate::model::xsd::*; -use crate::store::numeric_encoder::{EncodedQuad, EncodedTerm, StrHash}; -use crate::store::small_string::SmallString; +use crate::storage::numeric_encoder::{EncodedQuad, EncodedTerm, StrHash}; +use crate::storage::small_string::SmallString; use std::io; use std::io::{Cursor, Read}; use std::mem::size_of; @@ -627,7 +627,7 @@ pub fn write_term(sink: &mut Vec, term: EncodedTerm) { #[cfg(test)] mod tests { use super::*; - use crate::store::numeric_encoder::*; + use crate::storage::numeric_encoder::*; use std::collections::HashMap; use std::convert::Infallible; use std::sync::RwLock; diff --git a/lib/src/store/io.rs b/lib/src/storage/io.rs similarity index 98% rename from lib/src/store/io.rs rename to lib/src/storage/io.rs index 331addc0..cf6ae665 100644 --- a/lib/src/store/io.rs +++ b/lib/src/storage/io.rs @@ -3,8 +3,8 @@ use crate::error::invalid_input_error; use crate::io::{DatasetFormat, DatasetSerializer, GraphFormat, GraphSerializer}; use crate::model::{GraphNameRef, Quad, Triple}; -use crate::store::numeric_encoder::WriteEncoder; -use crate::store::storage::StorageLike; +use crate::storage::numeric_encoder::WriteEncoder; +use crate::storage::StorageLike; use oxiri::Iri; use rio_api::parser::{QuadsParser, TriplesParser}; use rio_turtle::{NQuadsParser, NTriplesParser, TriGParser, TurtleError, TurtleParser}; diff --git a/lib/src/store/storage.rs b/lib/src/storage/mod.rs similarity index 84% rename from lib/src/store/storage.rs rename to lib/src/storage/mod.rs index 1df781ed..21e6f938 100644 --- a/lib/src/store/storage.rs +++ b/lib/src/storage/mod.rs @@ -1,18 +1,31 @@ use std::error::Error; use std::fmt; -use std::io; use std::path::Path; 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 crate::error::invalid_data_error; use crate::sparql::EvaluationError; -use crate::store::binary_encoder::*; -use crate::store::io::StoreOrParseError; -use crate::store::numeric_encoder::*; +use crate::storage::binary_encoder::{ + decode_term, encode_term, encode_term_pair, encode_term_quad, encode_term_triple, + 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 #[derive(Clone)] @@ -32,15 +45,15 @@ pub struct Storage { } impl Storage { - pub fn new() -> Result { + pub fn new() -> Result { Self::do_open(&Config::new().temporary(true)) } - pub fn open(path: &Path) -> Result { + pub fn open(path: &Path) -> Result { Self::do_open(&Config::new().path(path)) } - fn do_open(config: &Config) -> Result { + fn do_open(config: &Config) -> Result { let db = config.open()?; let this = Self { default: db.clone(), @@ -84,7 +97,7 @@ impl Storage { } } - fn ensure_version(&self) -> Result { + fn ensure_version(&self) -> Result { Ok(if let Some(version) = self.default.get("oxversion")? { let mut buffer = [0; 8]; 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())?; Ok(()) } pub fn transaction( &self, - f: impl Fn(StorageTransaction<'_>) -> Result>, - ) -> Result> { + f: impl Fn(StorageTransaction<'_>) -> Result>, + ) -> Result> { Ok(( &self.id2str, &self.spog, @@ -144,7 +157,7 @@ impl Storage { self.gspo.is_empty() && self.dspo.is_empty() } - pub fn contains(&self, quad: &EncodedQuad) -> Result { + pub fn contains(&self, quad: &EncodedQuad) -> Result { let mut buffer = Vec::with_capacity(4 * WRITTEN_TERM_MAX_SIZE); if quad.graph_name.is_default_graph() { write_spo_quad(&mut buffer, quad); @@ -394,7 +407,7 @@ impl Storage { } } - pub fn contains_named_graph(&self, graph_name: EncodedTerm) -> Result { + pub fn contains_named_graph(&self, graph_name: EncodedTerm) -> Result { Ok(self.graphs.contains_key(&encode_term(graph_name))?) } @@ -446,7 +459,7 @@ impl Storage { } } - pub fn insert(&self, quad: &EncodedQuad) -> Result { + pub fn insert(&self, quad: &EncodedQuad) -> Result { let mut buffer = Vec::with_capacity(4 * WRITTEN_TERM_MAX_SIZE + 1); if quad.graph_name.is_default_graph() { @@ -501,7 +514,7 @@ impl Storage { } } - pub fn remove(&self, quad: &EncodedQuad) -> Result { + pub fn remove(&self, quad: &EncodedQuad) -> Result { let mut buffer = Vec::with_capacity(4 * WRITTEN_TERM_MAX_SIZE + 1); if quad.graph_name.is_default_graph() { @@ -553,11 +566,11 @@ impl Storage { } } - pub fn insert_named_graph(&self, graph_name: EncodedTerm) -> Result { + pub fn insert_named_graph(&self, graph_name: EncodedTerm) -> Result { 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() { self.dspo.clear()?; self.dpos.clear()?; @@ -570,14 +583,14 @@ impl Storage { Ok(()) } - pub fn remove_named_graph(&self, graph_name: EncodedTerm) -> Result { + pub fn remove_named_graph(&self, graph_name: EncodedTerm) -> Result { for quad in self.quads_for_graph(graph_name) { self.remove(&quad?)?; } 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.dpos.clear()?; self.dosp.clear()?; @@ -592,7 +605,7 @@ impl Storage { Ok(()) } - pub fn get_str(&self, key: StrHash) -> Result, io::Error> { + pub fn get_str(&self, key: StrHash) -> Result, std::io::Error> { self.id2str .get(key.to_be_bytes())? .map(|v| String::from_utf8(v.to_vec())) @@ -600,11 +613,11 @@ impl Storage { .map_err(invalid_data_error) } - pub fn contains_str(&self, key: StrHash) -> Result { + pub fn contains_str(&self, key: StrHash) -> Result { Ok(self.id2str.contains_key(key.to_be_bytes())?) } - pub fn insert_str(&self, key: StrHash, value: &str) -> Result { + pub fn insert_str(&self, key: StrHash, value: &str) -> Result { Ok(self.id2str.insert(key.to_be_bytes(), value)?.is_none()) } } @@ -631,9 +644,9 @@ impl ChainedDecodingQuadIterator { } impl Iterator for ChainedDecodingQuadIterator { - type Item = Result; + type Item = Result; - fn next(&mut self) -> Option> { + fn next(&mut self) -> Option> { if let Some(result) = self.first.next() { Some(result) } else if let Some(second) = self.second.as_mut() { @@ -650,9 +663,9 @@ pub struct DecodingQuadIterator { } impl Iterator for DecodingQuadIterator { - type Item = Result; + type Item = Result; - fn next(&mut self) -> Option> { + fn next(&mut self) -> Option> { Some(match self.iter.next()? { Ok((encoded, _)) => self.encoding.decode(&encoded), Err(error) => Err(error.into()), @@ -665,9 +678,9 @@ pub struct DecodingGraphIterator { } impl Iterator for DecodingGraphIterator { - type Item = Result; + type Item = Result; - fn next(&mut self) -> Option> { + fn next(&mut self) -> Option> { Some(match self.iter.next()? { Ok((encoded, _)) => decode_term(&encoded), Err(error) => Err(error.into()), @@ -690,7 +703,7 @@ pub struct StorageTransaction<'a> { } impl<'a> StorageTransaction<'a> { - pub fn insert(&self, quad: &EncodedQuad) -> Result { + pub fn insert(&self, quad: &EncodedQuad) -> Result { let mut buffer = Vec::with_capacity(4 * WRITTEN_TERM_MAX_SIZE + 1); if quad.graph_name.is_default_graph() { @@ -746,7 +759,7 @@ impl<'a> StorageTransaction<'a> { } } - pub fn remove(&self, quad: &EncodedQuad) -> Result { + pub fn remove(&self, quad: &EncodedQuad) -> Result { let mut buffer = Vec::with_capacity(4 * WRITTEN_TERM_MAX_SIZE + 1); if quad.graph_name.is_default_graph() { @@ -801,19 +814,19 @@ impl<'a> StorageTransaction<'a> { pub fn insert_named_graph( &self, graph_name: EncodedTerm, - ) -> Result { + ) -> Result { Ok(self.graphs.insert(encode_term(graph_name), &[])?.is_none()) } - pub fn get_str(&self, key: StrHash) -> Result, SledUnabortableTransactionError> { + pub fn get_str(&self, key: StrHash) -> Result, UnabortableTransactionError> { self.id2str .get(key.to_be_bytes())? .map(|v| String::from_utf8(v.to_vec())) .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 { + pub fn contains_str(&self, key: StrHash) -> Result { Ok(self.id2str.get(key.to_be_bytes())?.is_some()) } @@ -821,21 +834,21 @@ impl<'a> StorageTransaction<'a> { &self, key: StrHash, value: &str, - ) -> Result { + ) -> Result { Ok(self.id2str.insert(&key.to_be_bytes(), value)?.is_none()) } } /// Error returned by a Sled transaction #[derive(Debug)] -pub enum SledTransactionError { +pub enum TransactionError { /// A failure returned by the API user that have aborted the transaction Abort(T), /// A storage related error - Storage(io::Error), + Storage(std::io::Error), } -impl fmt::Display for SledTransactionError { +impl fmt::Display for TransactionError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Abort(e) => e.fmt(f), @@ -844,7 +857,7 @@ impl fmt::Display for SledTransactionError { } } -impl Error for SledTransactionError { +impl Error for TransactionError { fn source(&self) -> Option<&(dyn Error + 'static)> { match self { Self::Abort(e) => Some(e), @@ -853,20 +866,20 @@ impl Error for SledTransactionError { } } -impl From> for SledTransactionError { - fn from(e: TransactionError) -> Self { +impl From> for TransactionError { + fn from(e: Sled2TransactionError) -> Self { match e { - TransactionError::Abort(e) => Self::Abort(e), - TransactionError::Storage(e) => Self::Storage(e.into()), + Sled2TransactionError::Abort(e) => Self::Abort(e), + Sled2TransactionError::Storage(e) => Self::Storage(e.into()), } } } -impl> From> for io::Error { - fn from(e: SledTransactionError) -> Self { +impl> From> for std::io::Error { + fn from(e: TransactionError) -> Self { match e { - SledTransactionError::Abort(e) => e.into(), - SledTransactionError::Storage(e) => e, + TransactionError::Abort(e) => e.into(), + TransactionError::Storage(e) => e, } } } @@ -874,14 +887,14 @@ impl> From> for io::Error { /// An error returned from the transaction methods. /// Should be returned as it is #[derive(Debug)] -pub enum SledUnabortableTransactionError { +pub enum UnabortableTransactionError { #[doc(hidden)] Conflict, /// 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 { match self { 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)> { match self { Self::Storage(e) => Some(e), @@ -899,17 +912,17 @@ impl Error for SledUnabortableTransactionError { } } -impl From for EvaluationError { - fn from(e: SledUnabortableTransactionError) -> Self { +impl From for EvaluationError { + fn from(e: UnabortableTransactionError) -> Self { match e { - SledUnabortableTransactionError::Storage(e) => Self::Io(e), - SledUnabortableTransactionError::Conflict => Self::Conflict, + UnabortableTransactionError::Storage(e) => Self::Io(e), + UnabortableTransactionError::Conflict => Self::Conflict, } } } -impl From> for SledUnabortableTransactionError { - fn from(e: StoreOrParseError) -> Self { +impl From> for UnabortableTransactionError { + fn from(e: StoreOrParseError) -> Self { match e { StoreOrParseError::Store(e) => e, StoreOrParseError::Parse(e) => Self::Storage(e), @@ -917,27 +930,27 @@ impl From> for SledUnabortabl } } -impl From for SledUnabortableTransactionError { - fn from(e: UnabortableTransactionError) -> Self { +impl From for UnabortableTransactionError { + fn from(e: Sled2UnabortableTransactionError) -> Self { match e { - UnabortableTransactionError::Storage(e) => Self::Storage(e.into()), - UnabortableTransactionError::Conflict => Self::Conflict, + Sled2UnabortableTransactionError::Storage(e) => Self::Storage(e.into()), + Sled2UnabortableTransactionError::Conflict => Self::Conflict, } } } /// An error returned from the transaction closure #[derive(Debug)] -pub enum SledConflictableTransactionError { +pub enum ConflictableTransactionError { /// A failure returned by the user that will abort the transaction Abort(T), #[doc(hidden)] Conflict, /// A storage related error - Storage(io::Error), + Storage(std::io::Error), } -impl fmt::Display for SledConflictableTransactionError { +impl fmt::Display for ConflictableTransactionError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Conflict => write!(f, "Transaction conflict"), @@ -947,7 +960,7 @@ impl fmt::Display for SledConflictableTransactionError { } } -impl Error for SledConflictableTransactionError { +impl Error for ConflictableTransactionError { fn source(&self) -> Option<&(dyn Error + 'static)> { match self { Self::Abort(e) => Some(e), @@ -957,37 +970,37 @@ impl Error for SledConflictableTransactionError { } } -impl From for SledConflictableTransactionError { - fn from(e: SledUnabortableTransactionError) -> Self { +impl From for ConflictableTransactionError { + fn from(e: UnabortableTransactionError) -> Self { match e { - SledUnabortableTransactionError::Storage(e) => Self::Storage(e), - SledUnabortableTransactionError::Conflict => Self::Conflict, + UnabortableTransactionError::Storage(e) => Self::Storage(e), + UnabortableTransactionError::Conflict => Self::Conflict, } } } -impl From> for ConflictableTransactionError { - fn from(e: SledConflictableTransactionError) -> Self { +impl From> for Sled2ConflictableTransactionError { + fn from(e: ConflictableTransactionError) -> Self { match e { - SledConflictableTransactionError::Abort(e) => ConflictableTransactionError::Abort(e), - SledConflictableTransactionError::Conflict => ConflictableTransactionError::Conflict, - SledConflictableTransactionError::Storage(e) => { - ConflictableTransactionError::Storage(e.into()) + ConflictableTransactionError::Abort(e) => Sled2ConflictableTransactionError::Abort(e), + ConflictableTransactionError::Conflict => Sled2ConflictableTransactionError::Conflict, + ConflictableTransactionError::Storage(e) => { + Sled2ConflictableTransactionError::Storage(e.into()) } } } } impl StrEncodingAware for Storage { - type Error = io::Error; + type Error = std::io::Error; } impl StrLookup for Storage { - fn get_str(&self, id: StrHash) -> Result, io::Error> { + fn get_str(&self, id: StrHash) -> Result, std::io::Error> { self.get_str(id) } - fn get_str_id(&self, value: &str) -> Result, io::Error> { + fn get_str_id(&self, value: &str) -> Result, std::io::Error> { let key = StrHash::new(value); Ok(if self.contains_str(key)? { Some(key) @@ -998,7 +1011,7 @@ impl StrLookup for Storage { } impl StrContainer for Storage { - fn insert_str(&self, value: &str) -> Result { + fn insert_str(&self, value: &str) -> Result { let key = StrHash::new(value); self.insert_str(key, value)?; Ok(key) @@ -1006,15 +1019,15 @@ impl StrContainer for Storage { } impl<'a> StrEncodingAware for StorageTransaction<'a> { - type Error = SledUnabortableTransactionError; + type Error = UnabortableTransactionError; } impl<'a> StrLookup for StorageTransaction<'a> { - fn get_str(&self, id: StrHash) -> Result, SledUnabortableTransactionError> { + fn get_str(&self, id: StrHash) -> Result, UnabortableTransactionError> { self.get_str(id) } - fn get_str_id(&self, value: &str) -> Result, SledUnabortableTransactionError> { + fn get_str_id(&self, value: &str) -> Result, UnabortableTransactionError> { let key = StrHash::new(value); Ok(if self.contains_str(key)? { Some(key) @@ -1025,7 +1038,7 @@ impl<'a> StrLookup for StorageTransaction<'a> { } impl<'a> StrContainer for StorageTransaction<'a> { - fn insert_str(&self, value: &str) -> Result { + fn insert_str(&self, value: &str) -> Result { let key = StrHash::new(value); self.insert_str(key, value)?; Ok(key) diff --git a/lib/src/store/numeric_encoder.rs b/lib/src/storage/numeric_encoder.rs similarity index 99% rename from lib/src/store/numeric_encoder.rs rename to lib/src/storage/numeric_encoder.rs index 0216d5a3..5c718cce 100644 --- a/lib/src/store/numeric_encoder.rs +++ b/lib/src/storage/numeric_encoder.rs @@ -4,7 +4,7 @@ use crate::error::invalid_data_error; use crate::model::xsd::*; use crate::model::*; use crate::sparql::EvaluationError; -use crate::store::small_string::SmallString; +use crate::storage::small_string::SmallString; use rand::random; use rio_api::model as rio; use siphasher::sip128::{Hasher128, SipHasher24}; diff --git a/lib/src/store/small_string.rs b/lib/src/storage/small_string.rs similarity index 100% rename from lib/src/store/small_string.rs rename to lib/src/storage/small_string.rs diff --git a/lib/src/store/sled.rs b/lib/src/store.rs similarity index 85% rename from lib/src/store/sled.rs rename to lib/src/store.rs index c79e8c3b..fc776799 100644 --- a/lib/src/store/sled.rs +++ b/lib/src/store.rs @@ -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,_> = 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>::Ok(()) +//! ``` use std::convert::TryInto; use std::io::{BufRead, Write}; @@ -12,30 +41,33 @@ use crate::sparql::{ evaluate_query, evaluate_update, EvaluationError, Query, QueryOptions, QueryResults, Update, UpdateOptions, }; -use crate::store::io::{dump_dataset, dump_graph, load_dataset, load_graph}; -use crate::store::numeric_encoder::{ +use crate::storage::io::{dump_dataset, dump_graph, load_dataset, load_graph}; +use crate::storage::numeric_encoder::{ Decoder, EncodedTerm, ReadEncoder, StrContainer, StrEncodingAware, StrHash, StrLookup, WriteEncoder, }; -use crate::store::storage::*; -pub use crate::store::storage::{ - SledConflictableTransactionError, SledTransactionError, SledUnabortableTransactionError, +pub use crate::storage::ConflictableTransactionError; +pub use crate::storage::TransactionError; +pub use crate::storage::UnabortableTransactionError; +use crate::storage::{ + ChainedDecodingQuadIterator, DecodingGraphIterator, Storage, StorageTransaction, }; -/// 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 it using SPARQL. +/// An on-on disk [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset). +/// 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. /// /// Usage example: /// ``` -/// use oxigraph::SledStore; +/// use oxigraph::store::Store; /// use oxigraph::sparql::QueryResults; /// use oxigraph::model::*; /// # use std::fs::remove_dir_all; /// /// # { -/// let store = SledStore::open("example.db")?; +/// let store = Store::open("example.db")?; /// /// // insertion /// let ex = NamedNode::new("http://example.com")?; @@ -56,21 +88,21 @@ pub use crate::store::storage::{ /// # Result::<_,Box>::Ok(()) /// ``` #[derive(Clone)] -pub struct SledStore { +pub struct Store { storage: Storage, } //TODO: indexes for the default graph and indexes for the named graphs (no more Optional and space saving) -impl SledStore { - /// Creates a temporary [`SledStore`]() that will be deleted after drop. +impl Store { + /// Creates a temporary [`Store`]() that will be deleted after drop. pub fn new() -> Result { Ok(Self { 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) -> Result { Ok(Self { storage: Storage::open(path.as_ref())?, @@ -81,11 +113,11 @@ impl SledStore { /// /// Usage example: /// ``` - /// use oxigraph::SledStore; + /// use oxigraph::store::Store; /// use oxigraph::model::*; /// use oxigraph::sparql::QueryResults; /// - /// let store = SledStore::new()?; + /// let store = Store::new()?; /// /// // insertions /// let ex = NamedNodeRef::new("http://example.com")?; @@ -117,10 +149,10 @@ impl SledStore { /// /// Usage example: /// ``` - /// use oxigraph::SledStore; + /// use oxigraph::store::Store; /// use oxigraph::model::*; /// - /// let store = SledStore::new()?; + /// let store = Store::new()?; /// /// // insertion /// let ex = NamedNode::new("http://example.com")?; @@ -138,8 +170,8 @@ impl SledStore { predicate: Option>, object: Option>, graph_name: Option>, - ) -> SledQuadIter { - SledQuadIter { + ) -> QuadIter { + QuadIter { inner: match self.get_encoded_quad_pattern(subject, predicate, object, graph_name) { Ok(Some((subject, predicate, object, graph_name))) => QuadIterInner::Quads { iter: self @@ -209,7 +241,7 @@ impl SledStore { } /// 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) } @@ -241,10 +273,10 @@ impl SledStore { /// /// Usage example: /// ``` - /// use oxigraph::SledStore; + /// use oxigraph::store::Store; /// use oxigraph::model::*; /// - /// let store = SledStore::new()?; + /// let store = Store::new()?; /// /// // insertion /// store.update("INSERT DATA { }")?; @@ -281,12 +313,11 @@ impl SledStore { /// /// Usage example: /// ``` - /// use oxigraph::SledStore; + /// use oxigraph::store::{ConflictableTransactionError, Store}; /// use oxigraph::model::*; - /// use oxigraph::store::sled::SledConflictableTransactionError; /// use std::convert::Infallible; /// - /// let store = SledStore::new()?; + /// let store = Store::new()?; /// /// let ex = NamedNodeRef::new("http://example.com")?; /// let quad = QuadRef::new(ex, ex, ex, ex); @@ -294,7 +325,7 @@ impl SledStore { /// // transaction /// store.transaction(|transaction| { /// transaction.insert(quad)?; - /// Ok(()) as Result<(),SledConflictableTransactionError> + /// Ok(()) as Result<(),ConflictableTransactionError> /// })?; /// /// assert!(store.contains(quad)?); @@ -303,10 +334,10 @@ impl SledStore { /// ``` pub fn transaction( &self, - f: impl Fn(SledTransaction<'_>) -> Result>, - ) -> Result> { + f: impl Fn(Transaction<'_>) -> Result>, + ) -> Result> { self.storage - .transaction(|storage| f(SledTransaction { storage })) + .transaction(|storage| f(Transaction { storage })) } /// 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. /// 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. - /// 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: /// ``` - /// use oxigraph::SledStore; + /// use oxigraph::store::Store; /// use oxigraph::io::GraphFormat; /// use oxigraph::model::*; /// - /// let store = SledStore::new()?; + /// let store = Store::new()?; /// /// // insertion /// let file = b" ."; @@ -359,15 +390,15 @@ impl SledStore { /// 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. /// 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: /// ``` - /// use oxigraph::SledStore; + /// use oxigraph::store::Store; /// use oxigraph::io::DatasetFormat; /// use oxigraph::model::*; /// - /// let store = SledStore::new()?; + /// let store = Store::new()?; /// /// // insertion /// let file = b" ."; @@ -398,7 +429,7 @@ impl SledStore { /// /// 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. - /// 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>) -> Result { let quad = self.encode_quad(quad.into())?; self.storage.insert(&quad) @@ -410,7 +441,7 @@ impl SledStore { /// /// 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. - /// 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>) -> Result { if let Some(quad) = self.get_encoded_quad(quad.into())? { self.storage.remove(&quad) @@ -423,13 +454,13 @@ impl SledStore { /// /// Usage example: /// ``` - /// use oxigraph::SledStore; + /// use oxigraph::store::Store; /// use oxigraph::io::GraphFormat; /// use oxigraph::model::GraphName; /// /// let file = " .\n".as_bytes(); /// - /// let store = SledStore::new()?; + /// let store = Store::new()?; /// store.load_graph(file, GraphFormat::NTriples, &GraphName::DefaultGraph, None)?; /// /// let mut buffer = Vec::new(); @@ -454,12 +485,12 @@ impl SledStore { /// Dumps the store into a file. /// /// ``` - /// use oxigraph::SledStore; + /// use oxigraph::store::Store; /// use oxigraph::io::DatasetFormat; /// /// let file = " .\n".as_bytes(); /// - /// let store = SledStore::new()?; + /// let store = Store::new()?; /// store.load_dataset(file, DatasetFormat::NQuads, None)?; /// /// let mut buffer = Vec::new(); @@ -475,18 +506,18 @@ impl SledStore { /// /// Usage example: /// ``` - /// use oxigraph::SledStore; + /// use oxigraph::store::Store; /// use oxigraph::model::{NamedNode, QuadRef, NamedOrBlankNode}; /// /// 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, None))?; /// assert_eq!(vec![NamedOrBlankNode::from(ex)], store.named_graphs().collect::,_>>()?); /// # Result::<_,Box>::Ok(()) /// ``` - pub fn named_graphs(&self) -> SledGraphNameIter { - SledGraphNameIter { + pub fn named_graphs(&self) -> GraphNameIter { + GraphNameIter { iter: self.storage.named_graphs(), store: self.clone(), } @@ -496,11 +527,11 @@ impl SledStore { /// /// Usage example: /// ``` - /// use oxigraph::SledStore; + /// use oxigraph::store::Store; /// use oxigraph::model::{NamedNode, QuadRef}; /// /// let ex = NamedNode::new("http://example.com")?; - /// let store = SledStore::new()?; + /// let store = Store::new()?; /// store.insert(QuadRef::new(&ex, &ex, &ex, &ex))?; /// assert!(store.contains_named_graph(&ex)?); /// # Result::<_,Box>::Ok(()) @@ -522,11 +553,11 @@ impl SledStore { /// /// Usage example: /// ``` - /// use oxigraph::SledStore; + /// use oxigraph::store::Store; /// use oxigraph::model::NamedNodeRef; /// /// let ex = NamedNodeRef::new("http://example.com")?; - /// let store = SledStore::new()?; + /// let store = Store::new()?; /// store.insert_named_graph(ex)?; /// assert_eq!(store.named_graphs().count(), 1); /// # Result::<_,Box>::Ok(()) @@ -543,12 +574,12 @@ impl SledStore { /// /// Usage example: /// ``` - /// use oxigraph::SledStore; + /// use oxigraph::store::Store; /// use oxigraph::model::{NamedNodeRef, QuadRef}; /// /// let ex = NamedNodeRef::new("http://example.com")?; /// let quad = QuadRef::new(ex, ex, ex, ex); - /// let store = SledStore::new()?; + /// let store = Store::new()?; /// store.insert(quad)?; /// assert_eq!(1, store.len()); /// @@ -574,12 +605,12 @@ impl SledStore { /// /// Usage example: /// ``` - /// use oxigraph::SledStore; + /// use oxigraph::store::Store; /// use oxigraph::model::{NamedNodeRef, QuadRef}; /// /// let ex = NamedNodeRef::new("http://example.com")?; /// let quad = QuadRef::new(ex, ex, ex, ex); - /// let store = SledStore::new()?; + /// let store = Store::new()?; /// store.insert(quad)?; /// assert_eq!(1, store.len()); /// @@ -603,11 +634,11 @@ impl SledStore { /// /// Usage example: /// ``` - /// use oxigraph::SledStore; + /// use oxigraph::store::Store; /// use oxigraph::model::{NamedNodeRef, QuadRef}; /// /// 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, None))?; /// 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 { for t in self.iter() { 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; } -impl StrLookup for SledStore { +impl StrLookup for Store { fn get_str(&self, id: StrHash) -> Result, io::Error> { 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 { let key = StrHash::new(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`]. -pub struct SledTransaction<'a> { +/// Allows inserting and deleting quads during an ACID transaction with the [`Store`]. +pub struct Transaction<'a> { storage: StorageTransaction<'a>, } -impl SledTransaction<'_> { +impl Transaction<'_> { /// Loads a graph file (i.e. triples) into the store during the transaction. /// /// Warning: Because the load happens during a transaction, @@ -666,18 +697,18 @@ impl SledTransaction<'_> { /// /// Usage example: /// ``` - /// use oxigraph::SledStore; + /// use oxigraph::store::Store; /// use oxigraph::io::GraphFormat; /// use oxigraph::model::*; - /// use oxigraph::store::sled::SledConflictableTransactionError; + /// use oxigraph::store::ConflictableTransactionError; /// - /// let store = SledStore::new()?; + /// let store = Store::new()?; /// /// // insertion /// let file = b" ."; /// store.transaction(|transaction| { /// transaction.load_graph(file.as_ref(), GraphFormat::NTriples, &GraphName::DefaultGraph, None)?; - /// Ok(()) as Result<(),SledConflictableTransactionError> + /// Ok(()) as Result<(),ConflictableTransactionError> /// })?; /// /// // we inspect the store content @@ -699,7 +730,7 @@ impl SledTransaction<'_> { format: GraphFormat, to_graph_name: impl Into>, base_iri: Option<&str>, - ) -> Result<(), SledUnabortableTransactionError> { + ) -> Result<(), UnabortableTransactionError> { load_graph( &self.storage, reader, @@ -718,18 +749,18 @@ impl SledTransaction<'_> { /// /// Usage example: /// ``` - /// use oxigraph::SledStore; + /// use oxigraph::store::{Store, ConflictableTransactionError}; /// use oxigraph::io::DatasetFormat; /// use oxigraph::model::*; - /// use oxigraph::store::sled::SledConflictableTransactionError; + /// use oxigraph::store::ConflictableTransactionError; /// - /// let store = SledStore::new()?; + /// let store = Store::new()?; /// /// // insertion /// let file = b" ."; /// store.transaction(|transaction| { /// transaction.load_dataset(file.as_ref(), DatasetFormat::NQuads, None)?; - /// Ok(()) as Result<(),SledConflictableTransactionError> + /// Ok(()) as Result<(),ConflictableTransactionError> /// })?; /// /// // we inspect the store content @@ -750,7 +781,7 @@ impl SledTransaction<'_> { reader: impl BufRead, format: DatasetFormat, base_iri: Option<&str>, - ) -> Result<(), SledUnabortableTransactionError> { + ) -> Result<(), UnabortableTransactionError> { Ok(load_dataset(&self.storage, reader, format, base_iri)?) } @@ -760,7 +791,7 @@ impl SledTransaction<'_> { pub fn insert<'a>( &self, quad: impl Into>, - ) -> Result { + ) -> Result { let quad = self.encode_quad(quad.into())?; self.storage.insert(&quad) } @@ -771,7 +802,7 @@ impl SledTransaction<'_> { pub fn remove<'a>( &self, quad: impl Into>, - ) -> Result { + ) -> Result { if let Some(quad) = self.get_encoded_quad(quad.into())? { self.storage.remove(&quad) } else { @@ -785,49 +816,49 @@ impl SledTransaction<'_> { pub fn insert_named_graph<'a>( &self, graph_name: impl Into>, - ) -> Result { + ) -> Result { let graph_name = self.encode_named_or_blank_node(graph_name.into())?; self.storage.insert_named_graph(graph_name) } } -impl<'a> StrEncodingAware for &'a SledTransaction<'a> { - type Error = SledUnabortableTransactionError; +impl<'a> StrEncodingAware for &'a Transaction<'a> { + type Error = UnabortableTransactionError; } -impl<'a> StrLookup for &'a SledTransaction<'a> { - fn get_str(&self, id: StrHash) -> Result, SledUnabortableTransactionError> { +impl<'a> StrLookup for &'a Transaction<'a> { + fn get_str(&self, id: StrHash) -> Result, UnabortableTransactionError> { self.storage.get_str(id) } - fn get_str_id(&self, value: &str) -> Result, SledUnabortableTransactionError> { + fn get_str_id(&self, value: &str) -> Result, UnabortableTransactionError> { self.storage.get_str_id(value) } } -impl<'a> StrContainer for &'a SledTransaction<'a> { - fn insert_str(&self, value: &str) -> Result { +impl<'a> StrContainer for &'a Transaction<'a> { + fn insert_str(&self, value: &str) -> Result { let key = StrHash::new(value); self.storage.insert_str(key, value)?; Ok(key) } } -/// An iterator returning the quads contained in a [`SledStore`]. -pub struct SledQuadIter { +/// An iterator returning the quads contained in a [`Store`]. +pub struct QuadIter { inner: QuadIterInner, } enum QuadIterInner { Quads { iter: ChainedDecodingQuadIterator, - store: SledStore, + store: Store, }, Error(Once), Empty, } -impl Iterator for SledQuadIter { +impl Iterator for QuadIter { type Item = Result; fn next(&mut self) -> Option> { @@ -842,13 +873,13 @@ impl Iterator for SledQuadIter { } } -/// An iterator returning the graph names contained in a [`SledStore`]. -pub struct SledGraphNameIter { +/// An iterator returning the graph names contained in a [`Store`]. +pub struct GraphNameIter { iter: DecodingGraphIterator, - store: SledStore, + store: Store, } -impl Iterator for SledGraphNameIter { +impl Iterator for GraphNameIter { type Item = Result; fn next(&mut self) -> Option> { @@ -910,12 +941,12 @@ fn store() -> Result<(), io::Error> { named_quad.clone(), ]; - let store = SledStore::new()?; + let store = Store::new()?; for t in &default_quads { assert!(store.insert(t)?); } - let result: Result<_, SledTransactionError> = store.transaction(|t| { + let result: Result<_, TransactionError> = store.transaction(|t| { assert!(t.remove(&default_quad)?); assert_eq!(t.remove(&default_quad)?, false); assert!(t.insert(&named_quad)?); diff --git a/lib/src/store/mod.rs b/lib/src/store/mod.rs deleted file mode 100644 index 58286034..00000000 --- a/lib/src/store/mod.rs +++ /dev/null @@ -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; diff --git a/lib/tests/sled_store.rs b/lib/tests/store.rs similarity index 91% rename from lib/tests/sled_store.rs rename to lib/tests/store.rs index 6cf542a3..9f669449 100644 --- a/lib/tests/sled_store.rs +++ b/lib/tests/store.rs @@ -1,8 +1,8 @@ use oxigraph::io::{DatasetFormat, GraphFormat}; use oxigraph::model::vocab::{rdf, xsd}; use oxigraph::model::*; -use oxigraph::store::sled::SledConflictableTransactionError; -use oxigraph::SledStore; +use oxigraph::store::ConflictableTransactionError; +use oxigraph::store::Store; use std::io; use std::io::Cursor; use std::process::Command; @@ -77,7 +77,7 @@ fn quads(graph_name: impl Into>) -> Vec> #[test] fn test_load_graph() -> io::Result<()> { - let store = SledStore::new()?; + let store = Store::new()?; store.load_graph(Cursor::new(DATA), GraphFormat::Turtle, None, None)?; for q in quads(GraphNameRef::DefaultGraph) { assert!(store.contains(q)?); @@ -87,7 +87,7 @@ fn test_load_graph() -> io::Result<()> { #[test] fn test_load_dataset() -> io::Result<()> { - let store = SledStore::new()?; + let store = Store::new()?; store.load_dataset(Cursor::new(DATA), DatasetFormat::TriG, None)?; for q in quads(GraphNameRef::DefaultGraph) { assert!(store.contains(q)?); @@ -97,7 +97,7 @@ fn test_load_dataset() -> io::Result<()> { #[test] fn test_dump_graph() -> io::Result<()> { - let store = SledStore::new()?; + let store = Store::new()?; for q in quads(GraphNameRef::DefaultGraph) { store.insert(q)?; } @@ -113,7 +113,7 @@ fn test_dump_graph() -> io::Result<()> { #[test] fn test_dump_dataset() -> io::Result<()> { - let store = SledStore::new()?; + let store = Store::new()?; for q in quads(GraphNameRef::DefaultGraph) { store.insert(q)?; } @@ -129,10 +129,10 @@ fn test_dump_dataset() -> io::Result<()> { #[test] fn test_transaction_load_graph() -> io::Result<()> { - let store = SledStore::new()?; + let store = Store::new()?; store.transaction(|t| { t.load_graph(Cursor::new(DATA), GraphFormat::Turtle, None, None)?; - Ok(()) as Result<_, SledConflictableTransactionError> + Ok(()) as Result<_, ConflictableTransactionError> })?; for q in quads(GraphNameRef::DefaultGraph) { assert!(store.contains(q)?); @@ -142,10 +142,10 @@ fn test_transaction_load_graph() -> io::Result<()> { #[test] fn test_transaction_load_dataset() -> io::Result<()> { - let store = SledStore::new()?; + let store = Store::new()?; store.transaction(|t| { t.load_dataset(Cursor::new(DATA), DatasetFormat::TriG, None)?; - Ok(()) as Result<_, SledConflictableTransactionError> + Ok(()) as Result<_, ConflictableTransactionError> })?; for q in quads(GraphNameRef::DefaultGraph) { assert!(store.contains(q)?); @@ -156,7 +156,7 @@ fn test_transaction_load_dataset() -> io::Result<()> { #[test] 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) { assert!(store.contains(q)?); } diff --git a/python/src/store.rs b/python/src/store.rs index ead1d66c..8ce27cad 100644 --- a/python/src/store.rs +++ b/python/src/store.rs @@ -3,7 +3,7 @@ use crate::model::*; use crate::sparql::*; use oxigraph::io::{DatasetFormat, GraphFormat}; use oxigraph::model::GraphNameRef; -use oxigraph::store::sled::*; +use oxigraph::store::{self, Store}; use pyo3::exceptions::PyValueError; use pyo3::prelude::{ pyclass, pymethods, pyproto, Py, PyAny, PyObject, PyRef, PyRefMut, PyResult, Python, @@ -31,7 +31,7 @@ use std::io::BufReader; #[text_signature = "(path = None)"] #[derive(Clone)] pub struct PyStore { - inner: SledStore, + inner: Store, } #[pymethods] @@ -40,9 +40,9 @@ impl PyStore { fn new(path: Option<&str>) -> PyResult { Ok(Self { inner: if let Some(path) = path { - SledStore::open(path) + Store::open(path) } else { - SledStore::new() + Store::new() } .map_err(map_io_err)?, }) @@ -459,7 +459,7 @@ impl PyIterProtocol for PyStore { #[pyclass(unsendable, module = "oxigraph")] pub struct QuadIter { - inner: SledQuadIter, + inner: store::QuadIter, } #[pyproto] @@ -478,7 +478,7 @@ impl PyIterProtocol for QuadIter { #[pyclass(unsendable, module = "oxigraph")] pub struct GraphNameIter { - inner: SledGraphNameIter, + inner: store::GraphNameIter, } #[pyproto] diff --git a/server/src/main.rs b/server/src/main.rs index 07ec38a0..1e03256e 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -23,7 +23,7 @@ use http_types::{ use oxigraph::io::{DatasetFormat, GraphFormat}; use oxigraph::model::{GraphName, GraphNameRef, NamedNode, NamedOrBlankNode}; use oxigraph::sparql::{Query, QueryResults, QueryResultsFormat, Update}; -use oxigraph::SledStore as Store; +use oxigraph::store::Store; use oxiri::Iri; use rand::random; use std::io::BufReader; diff --git a/testsuite/src/files.rs b/testsuite/src/files.rs index 954b05d1..c06d0472 100644 --- a/testsuite/src/files.rs +++ b/testsuite/src/files.rs @@ -1,7 +1,7 @@ use anyhow::{anyhow, Result}; use oxigraph::io::{DatasetFormat, GraphFormat}; use oxigraph::model::{Dataset, Graph, GraphNameRef}; -use oxigraph::SledStore; +use oxigraph::store::Store; use std::fs::File; use std::io::{BufRead, BufReader, Read}; use std::path::PathBuf; @@ -41,7 +41,7 @@ pub fn read_file_to_string(url: &str) -> Result { pub fn load_to_store<'a>( url: &str, - store: &SledStore, + store: &Store, to_graph_name: impl Into>, ) -> Result<()> { if url.ends_with(".nt") { diff --git a/testsuite/src/sparql_evaluator.rs b/testsuite/src/sparql_evaluator.rs index caecfbcc..5432990b 100644 --- a/testsuite/src/sparql_evaluator.rs +++ b/testsuite/src/sparql_evaluator.rs @@ -7,7 +7,7 @@ use chrono::Utc; use oxigraph::model::vocab::*; use oxigraph::model::*; use oxigraph::sparql::*; -use oxigraph::SledStore; +use oxigraph::store::Store; use std::collections::HashMap; use std::str::FromStr; use std::sync::Arc; @@ -70,7 +70,7 @@ fn evaluate_sparql_test(test: &Test) -> Result<()> { } else if test.kind == "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 { load_to_store(data, &store, GraphNameRef::DefaultGraph)?; } @@ -190,7 +190,7 @@ fn evaluate_sparql_test(test: &Test) -> Result<()> { } else if test.kind == "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 { load_to_store(data, &store, &GraphName::DefaultGraph)?; } @@ -198,7 +198,7 @@ fn evaluate_sparql_test(test: &Test) -> Result<()> { load_to_store(value, &store, name)?; } - let result_store = SledStore::new()?; + let result_store = Store::new()?; if let Some(data) = &test.result { load_to_store(data, &result_store, &GraphName::DefaultGraph)?; } @@ -270,7 +270,7 @@ fn load_sparql_query_result(url: &str) -> Result { #[derive(Clone)] struct StaticServiceHandler { - services: Arc>, + services: Arc>, } impl StaticServiceHandler { @@ -281,7 +281,7 @@ impl StaticServiceHandler { .iter() .map(|(name, data)| { let name = NamedNode::new(name)?; - let store = SledStore::new()?; + let store = Store::new()?; load_to_store(&data, &store, &GraphName::DefaultGraph)?; Ok((name, store)) }) @@ -467,7 +467,7 @@ impl StaticQueryResults { fn from_graph(graph: Graph) -> StaticQueryResults { // Hack to normalize literals - let store = SledStore::new().unwrap(); + let store = Store::new().unwrap(); for t in graph.iter() { store .insert(t.in_graph(GraphNameRef::DefaultGraph)) diff --git a/wikibase/src/loader.rs b/wikibase/src/loader.rs index e70676c2..1e4d29d6 100644 --- a/wikibase/src/loader.rs +++ b/wikibase/src/loader.rs @@ -7,7 +7,7 @@ use http_client::HttpClient; use http_types::{headers, Method, Request, Result}; use oxigraph::io::GraphFormat; use oxigraph::model::NamedNodeRef; -use oxigraph::SledStore; +use oxigraph::store::Store; use serde_json::Value; use std::collections::{HashMap, HashSet}; use std::io::{BufReader, Cursor, Read}; @@ -16,7 +16,7 @@ use std::time::Duration; use url::{form_urlencoded, Url}; pub struct WikibaseLoader { - store: SledStore, + store: Store, client: H1Client, api_url: Url, entity_data_url: Url, @@ -28,7 +28,7 @@ pub struct WikibaseLoader { impl WikibaseLoader { pub fn new( - store: SledStore, + store: Store, api_url: &str, pages_base_url: &str, namespaces: &[u32], diff --git a/wikibase/src/main.rs b/wikibase/src/main.rs index cf419f7a..3f06019f 100644 --- a/wikibase/src/main.rs +++ b/wikibase/src/main.rs @@ -23,7 +23,7 @@ use http_types::{ use oxigraph::io::GraphFormat; use oxigraph::model::{GraphName, NamedNode, NamedOrBlankNode}; use oxigraph::sparql::{Query, QueryResults, QueryResultsFormat}; -use oxigraph::SledStore; +use oxigraph::store::Store; use std::str::FromStr; use std::time::Duration; use url::form_urlencoded; @@ -65,7 +65,7 @@ struct Args { pub async fn main() -> Result<()> { 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_base_url = args.mediawiki_base_url.clone(); let namespaces = args @@ -106,7 +106,7 @@ pub async fn main() -> Result<()> { .await } -async fn handle_request(request: Request, store: SledStore) -> Result { +async fn handle_request(request: Request, store: Store) -> Result { Ok(match (request.url().path(), request.method()) { ("/query", Method::Get) => { configure_and_evaluate_sparql_query(store, url_query(&request), None, request)? @@ -159,7 +159,7 @@ fn url_query(request: &Request) -> Vec { } fn configure_and_evaluate_sparql_query( - store: SledStore, + store: Store, encoded: Vec, mut query: Option, request: Request, @@ -187,7 +187,7 @@ fn configure_and_evaluate_sparql_query( } fn evaluate_sparql_query( - store: SledStore, + store: Store, query: String, default_graph_uris: Vec, named_graph_uris: Vec,