Adds explicit types for store quad iterators

pull/51/head
Tpt 4 years ago
parent cf67bda446
commit 4f3a5ad116
  1. 1
      CHANGELOG.md
  2. 62
      lib/src/store/memory.rs
  3. 53
      lib/src/store/rocksdb.rs
  4. 53
      lib/src/store/sled.rs
  5. 10
      python/src/memory_store.rs
  6. 11
      python/src/sled_store.rs

@ -5,6 +5,7 @@
- `QueryOptions::with_named_graph` now takes an `impl Into<NamedOrBlankNode>` instead of an `impl Into<NamedNode>`. - `QueryOptions::with_named_graph` now takes an `impl Into<NamedOrBlankNode>` instead of an `impl Into<NamedNode>`.
- `pyoxigraph` `query` methods now takes two new parameters, `default_graph` and `named_graphs`. `default_graph_uris` and `named_graph_uris` parameters are deprecated. - `pyoxigraph` `query` methods now takes two new parameters, `default_graph` and `named_graphs`. `default_graph_uris` and `named_graph_uris` parameters are deprecated.
- Fixes a bug in `xsd:gYear` parsing. - Fixes a bug in `xsd:gYear` parsing.
- Adds explicit types for quads iterators returned by stores.
## [0.1.0] - 2020-08-09 ## [0.1.0] - 2020-08-09

@ -175,7 +175,7 @@ impl MemoryStore {
predicate: Option<NamedNodeRef<'_>>, predicate: Option<NamedNodeRef<'_>>,
object: Option<TermRef<'_>>, object: Option<TermRef<'_>>,
graph_name: Option<GraphNameRef<'_>>, graph_name: Option<GraphNameRef<'_>>,
) -> impl Iterator<Item = Quad> { ) -> MemoryQuadIter {
let quads = if let Some((subject, predicate, object, graph_name)) = let quads = if let Some((subject, predicate, object, graph_name)) =
get_encoded_quad_pattern(self, subject, predicate, object, graph_name) get_encoded_quad_pattern(self, subject, predicate, object, graph_name)
.unwrap_infallible() .unwrap_infallible()
@ -184,10 +184,18 @@ impl MemoryStore {
} else { } else {
Vec::new() Vec::new()
}; };
let this = self.clone(); MemoryQuadIter {
quads.into_iter().map( iter: quads.into_iter(),
move |quad| this.decode_quad(&quad).unwrap(), // Could not fail store: self.clone(),
) }
}
/// Returns all the quads contained in the store
pub fn iter(&self) -> MemoryQuadIter {
MemoryQuadIter {
iter: self.encoded_quads().into_iter(),
store: self.clone(),
}
} }
/// Checks if this store contains a given quad /// Checks if this store contains a given quad
@ -424,11 +432,7 @@ impl MemoryStore {
/// # std::io::Result::Ok(()) /// # std::io::Result::Ok(())
/// ``` /// ```
pub fn dump_dataset(&self, writer: impl Write, format: DatasetFormat) -> Result<(), io::Error> { pub fn dump_dataset(&self, writer: impl Write, format: DatasetFormat) -> Result<(), io::Error> {
dump_dataset( dump_dataset(self.iter().map(Ok), writer, format)
self.quads_for_pattern(None, None, None, None).map(Ok),
writer,
format,
)
} }
#[allow(clippy::expect_used)] #[allow(clippy::expect_used)]
@ -1222,9 +1226,27 @@ impl Extend<Quad> for MemoryStore {
} }
} }
impl IntoIterator for MemoryStore {
type Item = Quad;
type IntoIter = MemoryQuadIter;
fn into_iter(self) -> MemoryQuadIter {
self.iter()
}
}
impl<'a> IntoIterator for &'a MemoryStore {
type Item = Quad;
type IntoIter = MemoryQuadIter;
fn into_iter(self) -> MemoryQuadIter {
self.iter()
}
}
impl fmt::Display for MemoryStore { impl fmt::Display for MemoryStore {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for t in self.quads_for_pattern(None, None, None, None) { for t in self {
writeln!(f, "{}", t)?; writeln!(f, "{}", t)?;
} }
Ok(()) Ok(())
@ -1254,6 +1276,24 @@ impl Iterator for EncodedQuadsIter {
} }
} }
/// An iterator returning the quads contained in a [`MemoryStore`](struct.MemoryStore.html).
pub struct MemoryQuadIter {
iter: IntoIter<EncodedQuad>,
store: MemoryStore,
}
impl Iterator for MemoryQuadIter {
type Item = Quad;
fn next(&mut self) -> Option<Quad> {
Some(self.store.decode_quad(&self.iter.next()?).unwrap())
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl StrId for LargeSpur {} impl StrId for LargeSpur {}
// Isomorphism implementation // Isomorphism implementation

@ -155,17 +155,24 @@ impl RocksDbStore {
predicate: Option<NamedNodeRef<'_>>, predicate: Option<NamedNodeRef<'_>>,
object: Option<TermRef<'_>>, object: Option<TermRef<'_>>,
graph_name: Option<GraphNameRef<'_>>, graph_name: Option<GraphNameRef<'_>>,
) -> impl Iterator<Item = Result<Quad, io::Error>> { ) -> RocksDbQuadIter {
match get_encoded_quad_pattern(self, subject, predicate, object, graph_name) { RocksDbQuadIter {
Ok(Some((subject, predicate, object, graph_name))) => QuadsIter::Quads { inner: match get_encoded_quad_pattern(self, subject, predicate, object, graph_name) {
iter: self.encoded_quads_for_pattern(subject, predicate, object, graph_name), Ok(Some((subject, predicate, object, graph_name))) => QuadIterInner::Quads {
store: self.clone(), iter: self.encoded_quads_for_pattern(subject, predicate, object, graph_name),
store: self.clone(),
},
Ok(None) => QuadIterInner::Empty,
Err(error) => QuadIterInner::Error(once(error)),
}, },
Ok(None) => QuadsIter::Empty,
Err(error) => QuadsIter::Error(once(error)),
} }
} }
/// Returns all the quads contained in the store
pub fn iter(&self) -> RocksDbQuadIter {
self.quads_for_pattern(None, None, None, None)
}
/// Checks if this store contains a given quad /// Checks if this store contains a given quad
pub fn contains<'a>(&self, quad: impl Into<QuadRef<'a>>) -> Result<bool, io::Error> { pub fn contains<'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())? {
@ -318,11 +325,7 @@ impl RocksDbStore {
/// ///
/// See [`MemoryStore`](../memory/struct.MemoryStore.html#method.dump_dataset) for a usage example. /// See [`MemoryStore`](../memory/struct.MemoryStore.html#method.dump_dataset) for a usage example.
pub fn dump_dataset(&self, writer: impl Write, syntax: DatasetFormat) -> Result<(), io::Error> { pub fn dump_dataset(&self, writer: impl Write, syntax: DatasetFormat) -> Result<(), io::Error> {
dump_dataset( dump_dataset(self.iter(), writer, syntax)
self.quads_for_pattern(None, None, None, None),
writer,
syntax,
)
} }
fn id2str_cf(&self) -> &ColumnFamily { fn id2str_cf(&self) -> &ColumnFamily {
@ -617,7 +620,7 @@ impl RocksDbStore {
impl fmt::Display for RocksDbStore { impl fmt::Display for RocksDbStore {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for t in self.quads_for_pattern(None, None, None, None) { for t in self.iter() {
writeln!(f, "{}", t.map_err(|_| fmt::Error)?)?; writeln!(f, "{}", t.map_err(|_| fmt::Error)?)?;
} }
Ok(()) Ok(())
@ -1161,7 +1164,12 @@ fn map_err(e: Error) -> io::Error {
io::Error::new(io::ErrorKind::Other, e) io::Error::new(io::ErrorKind::Other, e)
} }
enum QuadsIter { /// An iterator returning the quads contained in a [`RocksDbStore`](struct.RocksDbStore.html).
pub struct RocksDbQuadIter {
inner: QuadIterInner,
}
enum QuadIterInner {
Quads { Quads {
iter: DecodingIndexesIterator, iter: DecodingIndexesIterator,
store: RocksDbStore, store: RocksDbStore,
@ -1170,17 +1178,17 @@ enum QuadsIter {
Empty, Empty,
} }
impl Iterator for QuadsIter { impl Iterator for RocksDbQuadIter {
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>> {
match self { match &mut self.inner {
Self::Quads { iter, store } => Some(match iter.next()? { QuadIterInner::Quads { iter, store } => Some(match iter.next()? {
Ok(quad) => store.decode_quad(&quad).map_err(|e| e.into()), Ok(quad) => store.decode_quad(&quad).map_err(|e| e.into()),
Err(error) => Err(error), Err(error) => Err(error),
}), }),
Self::Error(iter) => iter.next().map(Err), QuadIterInner::Error(iter) => iter.next().map(Err),
Self::Empty => None, QuadIterInner::Empty => None,
} }
} }
} }
@ -1242,12 +1250,7 @@ fn store() -> Result<(), io::Error> {
})?; })?;
assert_eq!(store.len(), 4); assert_eq!(store.len(), 4);
assert_eq!( assert_eq!(store.iter().collect::<Result<Vec<_>, _>>()?, all_quads);
store
.quads_for_pattern(None, None, None, None)
.collect::<Result<Vec<_>, _>>()?,
all_quads
);
assert_eq!( assert_eq!(
store store
.quads_for_pattern(Some(main_s.as_ref()), None, None, None) .quads_for_pattern(Some(main_s.as_ref()), None, None, None)

@ -164,17 +164,24 @@ impl SledStore {
predicate: Option<NamedNodeRef<'_>>, predicate: Option<NamedNodeRef<'_>>,
object: Option<TermRef<'_>>, object: Option<TermRef<'_>>,
graph_name: Option<GraphNameRef<'_>>, graph_name: Option<GraphNameRef<'_>>,
) -> impl Iterator<Item = Result<Quad, io::Error>> { ) -> SledQuadIter {
match get_encoded_quad_pattern(self, subject, predicate, object, graph_name) { SledQuadIter {
Ok(Some((subject, predicate, object, graph_name))) => QuadsIter::Quads { inner: match get_encoded_quad_pattern(self, subject, predicate, object, graph_name) {
iter: self.encoded_quads_for_pattern(subject, predicate, object, graph_name), Ok(Some((subject, predicate, object, graph_name))) => QuadIterInner::Quads {
store: self.clone(), iter: self.encoded_quads_for_pattern(subject, predicate, object, graph_name),
store: self.clone(),
},
Ok(None) => QuadIterInner::Empty,
Err(error) => QuadIterInner::Error(once(error)),
}, },
Ok(None) => QuadsIter::Empty,
Err(error) => QuadsIter::Error(once(error)),
} }
} }
/// Returns all the quads contained in the store
pub fn iter(&self) -> SledQuadIter {
self.quads_for_pattern(None, None, None, None)
}
/// Checks if this store contains a given quad /// Checks if this store contains a given quad
pub fn contains<'a>(&self, quad: impl Into<QuadRef<'a>>) -> Result<bool, io::Error> { pub fn contains<'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())? {
@ -352,11 +359,7 @@ impl SledStore {
/// ///
/// See [`MemoryStore`](../memory/struct.MemoryStore.html#method.dump_dataset) for a usage example. /// See [`MemoryStore`](../memory/struct.MemoryStore.html#method.dump_dataset) for a usage example.
pub fn dump_dataset(&self, writer: impl Write, format: DatasetFormat) -> Result<(), io::Error> { pub fn dump_dataset(&self, writer: impl Write, format: DatasetFormat) -> Result<(), io::Error> {
dump_dataset( dump_dataset(self.iter(), writer, format)
self.quads_for_pattern(None, None, None, None),
writer,
format,
)
} }
fn contains_encoded(&self, quad: &EncodedQuad) -> Result<bool, io::Error> { fn contains_encoded(&self, quad: &EncodedQuad) -> Result<bool, io::Error> {
@ -590,7 +593,7 @@ impl SledStore {
impl fmt::Display for SledStore { impl fmt::Display for SledStore {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for t in self.quads_for_pattern(None, None, None, None) { for t in self.iter() {
writeln!(f, "{}", t.map_err(|_| fmt::Error)?)?; writeln!(f, "{}", t.map_err(|_| fmt::Error)?)?;
} }
Ok(()) Ok(())
@ -1217,7 +1220,12 @@ impl Iterator for DecodingQuadIterator {
} }
} }
enum QuadsIter { /// An iterator returning the quads contained in a [`SledStore`](struct.SledStore.html).
pub struct SledQuadIter {
inner: QuadIterInner,
}
enum QuadIterInner {
Quads { Quads {
iter: DecodingQuadsIterator, iter: DecodingQuadsIterator,
store: SledStore, store: SledStore,
@ -1226,17 +1234,17 @@ enum QuadsIter {
Empty, Empty,
} }
impl Iterator for QuadsIter { impl Iterator for SledQuadIter {
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>> {
match self { match &mut self.inner {
Self::Quads { iter, store } => Some(match iter.next()? { QuadIterInner::Quads { iter, store } => Some(match iter.next()? {
Ok(quad) => store.decode_quad(&quad).map_err(|e| e.into()), Ok(quad) => store.decode_quad(&quad).map_err(|e| e.into()),
Err(error) => Err(error), Err(error) => Err(error),
}), }),
Self::Error(iter) => iter.next().map(Err), QuadIterInner::Error(iter) => iter.next().map(Err),
Self::Empty => None, QuadIterInner::Empty => None,
} }
} }
} }
@ -1293,12 +1301,7 @@ fn store() -> Result<(), io::Error> {
result?; result?;
assert_eq!(store.len(), 4); assert_eq!(store.len(), 4);
assert_eq!( assert_eq!(store.iter().collect::<Result<Vec<_>, _>>()?, all_quads);
store
.quads_for_pattern(None, None, None, None)
.collect::<Result<Vec<_>, _>>()?,
all_quads
);
assert_eq!( assert_eq!(
store store
.quads_for_pattern(Some(main_s.as_ref()), None, None, None) .quads_for_pattern(Some(main_s.as_ref()), None, None, None)

@ -4,7 +4,7 @@ use crate::sparql::*;
use crate::store_utils::*; use crate::store_utils::*;
use oxigraph::io::{DatasetFormat, GraphFormat}; use oxigraph::io::{DatasetFormat, GraphFormat};
use oxigraph::model::*; use oxigraph::model::*;
use oxigraph::MemoryStore; use oxigraph::store::memory::*;
use pyo3::basic::CompareOp; use pyo3::basic::CompareOp;
use pyo3::exceptions::{NotImplementedError, ValueError}; use pyo3::exceptions::{NotImplementedError, ValueError};
use pyo3::prelude::*; use pyo3::prelude::*;
@ -95,12 +95,12 @@ impl PyMemoryStore {
let (subject, predicate, object, graph_name) = let (subject, predicate, object, graph_name) =
extract_quads_pattern(subject, predicate, object, graph_name)?; extract_quads_pattern(subject, predicate, object, graph_name)?;
Ok(QuadIter { Ok(QuadIter {
inner: Box::new(self.inner.quads_for_pattern( inner: self.inner.quads_for_pattern(
subject.as_ref().map(|t| t.into()), subject.as_ref().map(|t| t.into()),
predicate.as_ref().map(|t| t.into()), predicate.as_ref().map(|t| t.into()),
object.as_ref().map(|t| t.into()), object.as_ref().map(|t| t.into()),
graph_name.as_ref().map(|t| t.into()), graph_name.as_ref().map(|t| t.into()),
)), ),
}) })
} }
@ -351,14 +351,14 @@ impl<'p> PySequenceProtocol<'p> for PyMemoryStore {
impl PyIterProtocol for PyMemoryStore { impl PyIterProtocol for PyMemoryStore {
fn __iter__(slf: PyRef<Self>) -> QuadIter { fn __iter__(slf: PyRef<Self>) -> QuadIter {
QuadIter { QuadIter {
inner: Box::new(slf.inner.quads_for_pattern(None, None, None, None)), inner: slf.inner.iter(),
} }
} }
} }
#[pyclass(unsendable)] #[pyclass(unsendable)]
pub struct QuadIter { pub struct QuadIter {
inner: Box<dyn Iterator<Item = Quad>>, inner: MemoryQuadIter,
} }
#[pyproto] #[pyproto]

@ -4,11 +4,10 @@ use crate::sparql::*;
use crate::store_utils::*; use crate::store_utils::*;
use oxigraph::io::{DatasetFormat, GraphFormat}; use oxigraph::io::{DatasetFormat, GraphFormat};
use oxigraph::model::*; use oxigraph::model::*;
use oxigraph::SledStore; use oxigraph::store::sled::*;
use pyo3::exceptions::ValueError; use pyo3::exceptions::ValueError;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::{PyIterProtocol, PyObjectProtocol, PySequenceProtocol}; use pyo3::{PyIterProtocol, PyObjectProtocol, PySequenceProtocol};
use std::io;
use std::io::BufReader; use std::io::BufReader;
/// Store based on the `Sled <https://sled.rs/>`_ key-value database. /// Store based on the `Sled <https://sled.rs/>`_ key-value database.
@ -110,12 +109,12 @@ impl PySledStore {
let (subject, predicate, object, graph_name) = let (subject, predicate, object, graph_name) =
extract_quads_pattern(subject, predicate, object, graph_name)?; extract_quads_pattern(subject, predicate, object, graph_name)?;
Ok(QuadIter { Ok(QuadIter {
inner: Box::new(self.inner.quads_for_pattern( inner: self.inner.quads_for_pattern(
subject.as_ref().map(|t| t.into()), subject.as_ref().map(|t| t.into()),
predicate.as_ref().map(|t| t.into()), predicate.as_ref().map(|t| t.into()),
object.as_ref().map(|t| t.into()), object.as_ref().map(|t| t.into()),
graph_name.as_ref().map(|t| t.into()), graph_name.as_ref().map(|t| t.into()),
)), ),
}) })
} }
@ -360,14 +359,14 @@ impl PySequenceProtocol for PySledStore {
impl PyIterProtocol for PySledStore { impl PyIterProtocol for PySledStore {
fn __iter__(slf: PyRef<Self>) -> QuadIter { fn __iter__(slf: PyRef<Self>) -> QuadIter {
QuadIter { QuadIter {
inner: Box::new(slf.inner.quads_for_pattern(None, None, None, None)), inner: slf.inner.iter(),
} }
} }
} }
#[pyclass(unsendable)] #[pyclass(unsendable)]
pub struct QuadIter { pub struct QuadIter {
inner: Box<dyn Iterator<Item = Result<Quad, io::Error>>>, inner: SledQuadIter,
} }
#[pyproto] #[pyproto]

Loading…
Cancel
Save