StrContainer does not need to be mutable

pull/171/head
Tpt 3 years ago
parent be4a5b0b6b
commit 5ea4f2f95a
  1. 2
      lib/src/sparql/dataset.rs
  2. 4
      lib/src/sparql/eval.rs
  3. 26
      lib/src/store/binary_encoder.rs
  4. 45
      lib/src/store/numeric_encoder.rs
  5. 107
      lib/src/store/sled.rs
  6. 142
      lib/src/store/storage.rs
  7. 21
      python/src/store.rs

@ -199,7 +199,7 @@ impl<S: ReadableEncodedStore + 'static> ReadableEncodedStore for DatasetView<S>
} }
impl<'a, S: ReadableEncodedStore> StrContainer for &'a DatasetView<S> { impl<'a, S: ReadableEncodedStore> StrContainer for &'a DatasetView<S> {
fn insert_str(&mut self, value: &str) -> Result<StrHash, EvaluationError> { fn insert_str(&self, value: &str) -> Result<StrHash, EvaluationError> {
if let Some(hash) = self.store.get_str_id(value).map_err(|e| e.into())? { if let Some(hash) = self.store.get_str_id(value).map_err(|e| e.into())? {
Ok(hash) Ok(hash)
} else { } else {

@ -1377,7 +1377,7 @@ where
} else { } else {
None None
}?; }?;
let mut encoder = self.dataset.as_ref(); let encoder = self.dataset.as_ref();
encoder encoder
.encode_literal(LiteralRef::new_typed_literal( .encode_literal(LiteralRef::new_typed_literal(
&value, &value,
@ -1823,7 +1823,7 @@ where
) -> EncodedTuplesIterator { ) -> EncodedTuplesIterator {
let eval = self.clone(); let eval = self.clone();
Box::new(iter.map(move |solution| { Box::new(iter.map(move |solution| {
let mut encoder = eval.dataset.as_ref(); let encoder = eval.dataset.as_ref();
let mut encoded_terms = EncodedTuple::with_capacity(variables.len()); let mut encoded_terms = EncodedTuple::with_capacity(variables.len());
for (variable, term) in solution?.iter() { for (variable, term) in solution?.iter() {
put_variable_value( put_variable_value(

@ -630,17 +630,11 @@ mod tests {
use crate::store::numeric_encoder::*; use crate::store::numeric_encoder::*;
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::Infallible; use std::convert::Infallible;
use std::sync::RwLock;
#[derive(Default)]
struct MemoryStrStore { struct MemoryStrStore {
id2str: HashMap<StrHash, String>, id2str: RwLock<HashMap<StrHash, String>>,
}
impl Default for MemoryStrStore {
fn default() -> Self {
Self {
id2str: HashMap::default(),
}
}
} }
impl StrEncodingAware for MemoryStrStore { impl StrEncodingAware for MemoryStrStore {
@ -649,12 +643,12 @@ mod tests {
impl StrLookup for MemoryStrStore { impl StrLookup for MemoryStrStore {
fn get_str(&self, id: StrHash) -> Result<Option<String>, Infallible> { fn get_str(&self, id: StrHash) -> Result<Option<String>, Infallible> {
Ok(self.id2str.get(&id).cloned()) Ok(self.id2str.read().unwrap().get(&id).cloned())
} }
fn get_str_id(&self, value: &str) -> Result<Option<StrHash>, Infallible> { fn get_str_id(&self, value: &str) -> Result<Option<StrHash>, Infallible> {
let id = StrHash::new(value); let id = StrHash::new(value);
Ok(if self.id2str.contains_key(&id) { Ok(if self.id2str.read().unwrap().contains_key(&id) {
Some(id) Some(id)
} else { } else {
None None
@ -663,9 +657,13 @@ mod tests {
} }
impl StrContainer for MemoryStrStore { impl StrContainer for MemoryStrStore {
fn insert_str(&mut self, value: &str) -> Result<StrHash, Infallible> { fn insert_str(&self, value: &str) -> Result<StrHash, Infallible> {
let key = StrHash::new(value); let key = StrHash::new(value);
self.id2str.entry(key).or_insert_with(|| value.to_owned()); self.id2str
.write()
.unwrap()
.entry(key)
.or_insert_with(|| value.to_owned());
Ok(key) Ok(key)
} }
} }
@ -675,7 +673,7 @@ mod tests {
use crate::model::vocab::xsd; use crate::model::vocab::xsd;
use crate::model::*; use crate::model::*;
let mut store = MemoryStrStore::default(); let store = MemoryStrStore::default();
let terms: Vec<Term> = vec![ let terms: Vec<Term> = vec![
NamedNode::new_unchecked("http://foo.com").into(), NamedNode::new_unchecked("http://foo.com").into(),
NamedNode::new_unchecked("http://bar.com").into(), NamedNode::new_unchecked("http://bar.com").into(),

@ -502,7 +502,7 @@ pub(crate) trait StrLookup: StrEncodingAware {
} }
pub(crate) trait StrContainer: StrEncodingAware { pub(crate) trait StrContainer: StrEncodingAware {
fn insert_str(&mut self, value: &str) -> Result<StrHash, Self::Error>; fn insert_str(&self, value: &str) -> Result<StrHash, Self::Error>;
} }
/// Tries to encode a term based on the existing strings (does not insert anything) /// Tries to encode a term based on the existing strings (does not insert anything)
@ -744,17 +744,11 @@ impl<S: StrLookup> ReadEncoder for S {
/// Encodes a term and insert strings if needed /// Encodes a term and insert strings if needed
pub(crate) trait WriteEncoder: StrEncodingAware { pub(crate) trait WriteEncoder: StrEncodingAware {
fn encode_named_node( fn encode_named_node(&self, named_node: NamedNodeRef<'_>) -> Result<EncodedTerm, Self::Error> {
&mut self,
named_node: NamedNodeRef<'_>,
) -> Result<EncodedTerm, Self::Error> {
self.encode_rio_named_node(named_node.into()) self.encode_rio_named_node(named_node.into())
} }
fn encode_blank_node( fn encode_blank_node(&self, blank_node: BlankNodeRef<'_>) -> Result<EncodedTerm, Self::Error> {
&mut self,
blank_node: BlankNodeRef<'_>,
) -> Result<EncodedTerm, Self::Error> {
Ok(if let Some(id) = blank_node.id() { Ok(if let Some(id) = blank_node.id() {
EncodedTerm::NumericalBlankNode { id } EncodedTerm::NumericalBlankNode { id }
} else { } else {
@ -769,12 +763,12 @@ pub(crate) trait WriteEncoder: StrEncodingAware {
}) })
} }
fn encode_literal(&mut self, literal: LiteralRef<'_>) -> Result<EncodedTerm, Self::Error> { fn encode_literal(&self, literal: LiteralRef<'_>) -> Result<EncodedTerm, Self::Error> {
self.encode_rio_literal(literal.into()) self.encode_rio_literal(literal.into())
} }
fn encode_named_or_blank_node( fn encode_named_or_blank_node(
&mut self, &self,
term: NamedOrBlankNodeRef<'_>, term: NamedOrBlankNodeRef<'_>,
) -> Result<EncodedTerm, Self::Error> { ) -> Result<EncodedTerm, Self::Error> {
match term { match term {
@ -783,7 +777,7 @@ pub(crate) trait WriteEncoder: StrEncodingAware {
} }
} }
fn encode_term(&mut self, term: TermRef<'_>) -> Result<EncodedTerm, Self::Error> { fn encode_term(&self, term: TermRef<'_>) -> Result<EncodedTerm, Self::Error> {
match term { match term {
TermRef::NamedNode(named_node) => self.encode_named_node(named_node), TermRef::NamedNode(named_node) => self.encode_named_node(named_node),
TermRef::BlankNode(blank_node) => self.encode_blank_node(blank_node), TermRef::BlankNode(blank_node) => self.encode_blank_node(blank_node),
@ -791,7 +785,7 @@ pub(crate) trait WriteEncoder: StrEncodingAware {
} }
} }
fn encode_graph_name(&mut self, name: GraphNameRef<'_>) -> Result<EncodedTerm, Self::Error> { fn encode_graph_name(&self, name: GraphNameRef<'_>) -> Result<EncodedTerm, Self::Error> {
match name { match name {
GraphNameRef::NamedNode(named_node) => self.encode_named_node(named_node), GraphNameRef::NamedNode(named_node) => self.encode_named_node(named_node),
GraphNameRef::BlankNode(blank_node) => self.encode_blank_node(blank_node), GraphNameRef::BlankNode(blank_node) => self.encode_blank_node(blank_node),
@ -799,7 +793,7 @@ pub(crate) trait WriteEncoder: StrEncodingAware {
} }
} }
fn encode_quad(&mut self, quad: QuadRef<'_>) -> Result<EncodedQuad, Self::Error> { fn encode_quad(&self, quad: QuadRef<'_>) -> Result<EncodedQuad, Self::Error> {
Ok(EncodedQuad { Ok(EncodedQuad {
subject: self.encode_named_or_blank_node(quad.subject)?, subject: self.encode_named_or_blank_node(quad.subject)?,
predicate: self.encode_named_node(quad.predicate)?, predicate: self.encode_named_node(quad.predicate)?,
@ -809,7 +803,7 @@ pub(crate) trait WriteEncoder: StrEncodingAware {
} }
fn encode_triple_in_graph( fn encode_triple_in_graph(
&mut self, &self,
triple: TripleRef<'_>, triple: TripleRef<'_>,
graph_name: EncodedTerm, graph_name: EncodedTerm,
) -> Result<EncodedQuad, Self::Error> { ) -> Result<EncodedQuad, Self::Error> {
@ -822,7 +816,7 @@ pub(crate) trait WriteEncoder: StrEncodingAware {
} }
fn encode_rio_named_node( fn encode_rio_named_node(
&mut self, &self,
named_node: rio::NamedNode<'_>, named_node: rio::NamedNode<'_>,
) -> Result<EncodedTerm, Self::Error> { ) -> Result<EncodedTerm, Self::Error> {
Ok(EncodedTerm::NamedNode { Ok(EncodedTerm::NamedNode {
@ -831,7 +825,7 @@ pub(crate) trait WriteEncoder: StrEncodingAware {
} }
fn encode_rio_blank_node( fn encode_rio_blank_node(
&mut self, &self,
blank_node: rio::BlankNode<'_>, blank_node: rio::BlankNode<'_>,
bnodes_map: &mut HashMap<String, u128>, bnodes_map: &mut HashMap<String, u128>,
) -> Result<EncodedTerm, Self::Error> { ) -> Result<EncodedTerm, Self::Error> {
@ -843,10 +837,7 @@ pub(crate) trait WriteEncoder: StrEncodingAware {
EncodedTerm::NumericalBlankNode { id } EncodedTerm::NumericalBlankNode { id }
}) })
} }
fn encode_rio_literal( fn encode_rio_literal(&self, literal: rio::Literal<'_>) -> Result<EncodedTerm, Self::Error> {
&mut self,
literal: rio::Literal<'_>,
) -> Result<EncodedTerm, Self::Error> {
Ok(match literal { Ok(match literal {
rio::Literal::Simple { value } => { rio::Literal::Simple { value } => {
if let Ok(value) = SmallString::try_from(value) { if let Ok(value) = SmallString::try_from(value) {
@ -949,7 +940,7 @@ pub(crate) trait WriteEncoder: StrEncodingAware {
} }
fn encode_rio_named_or_blank_node( fn encode_rio_named_or_blank_node(
&mut self, &self,
term: rio::NamedOrBlankNode<'_>, term: rio::NamedOrBlankNode<'_>,
bnodes_map: &mut HashMap<String, u128>, bnodes_map: &mut HashMap<String, u128>,
) -> Result<EncodedTerm, Self::Error> { ) -> Result<EncodedTerm, Self::Error> {
@ -962,7 +953,7 @@ pub(crate) trait WriteEncoder: StrEncodingAware {
} }
fn encode_rio_term( fn encode_rio_term(
&mut self, &self,
term: rio::Term<'_>, term: rio::Term<'_>,
bnodes_map: &mut HashMap<String, u128>, bnodes_map: &mut HashMap<String, u128>,
) -> Result<EncodedTerm, Self::Error> { ) -> Result<EncodedTerm, Self::Error> {
@ -974,7 +965,7 @@ pub(crate) trait WriteEncoder: StrEncodingAware {
} }
fn encode_rio_quad( fn encode_rio_quad(
&mut self, &self,
quad: rio::Quad<'_>, quad: rio::Quad<'_>,
bnodes_map: &mut HashMap<String, u128>, bnodes_map: &mut HashMap<String, u128>,
) -> Result<EncodedQuad, Self::Error> { ) -> Result<EncodedQuad, Self::Error> {
@ -990,7 +981,7 @@ pub(crate) trait WriteEncoder: StrEncodingAware {
} }
fn encode_rio_triple_in_graph( fn encode_rio_triple_in_graph(
&mut self, &self,
triple: rio::Triple<'_>, triple: rio::Triple<'_>,
graph_name: EncodedTerm, graph_name: EncodedTerm,
bnodes_map: &mut HashMap<String, u128>, bnodes_map: &mut HashMap<String, u128>,
@ -1003,11 +994,11 @@ pub(crate) trait WriteEncoder: StrEncodingAware {
}) })
} }
fn encode_str(&mut self, value: &str) -> Result<StrHash, Self::Error>; fn encode_str(&self, value: &str) -> Result<StrHash, Self::Error>;
} }
impl<S: StrContainer> WriteEncoder for S { impl<S: StrContainer> WriteEncoder for S {
fn encode_str(&mut self, value: &str) -> Result<StrHash, Self::Error> { fn encode_str(&self, value: &str) -> Result<StrHash, Self::Error> {
self.insert_str(value) self.insert_str(value)
} }
} }

@ -336,26 +336,28 @@ impl SledStore {
/// Adds a quad to this store. /// Adds a quad to this store.
/// ///
/// Returns `true` if the quad was not already in the store.
///
/// 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](SledStore::transaction()) if you do not want that.
pub fn insert<'a>(&self, quad: impl Into<QuadRef<'a>>) -> Result<(), io::Error> { pub fn insert<'a>(&self, quad: impl Into<QuadRef<'a>>) -> Result<bool, io::Error> {
let mut this = self; let quad = self.encode_quad(quad.into())?;
let quad = this.encode_quad(quad.into())?; self.storage.insert(&quad)
this.insert_encoded(&quad)
} }
/// Removes a quad from this store. /// Removes a quad from this store.
/// ///
/// Returns `true` if the quad was in the store and has been removed.
///
/// 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](SledStore::transaction()) if you do not want that.
pub fn remove<'a>(&self, quad: impl Into<QuadRef<'a>>) -> Result<(), 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())? {
let mut this = self; self.storage.remove(&quad)
this.remove_encoded(&quad)
} else { } else {
Ok(()) Ok(false)
} }
} }
@ -458,6 +460,8 @@ impl SledStore {
/// Inserts a graph into this store /// Inserts a graph into this store
/// ///
/// Returns `true` if the graph was not already in the store.
///
/// Usage example: /// Usage example:
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::SledStore;
@ -472,10 +476,9 @@ impl SledStore {
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<(), io::Error> { ) -> Result<bool, io::Error> {
let mut this = self; let graph_name = self.encode_named_or_blank_node(graph_name.into())?;
let graph_name = this.encode_named_or_blank_node(graph_name.into())?; self.storage.insert_named_graph(graph_name)
this.insert_encoded_named_graph(graph_name)
} }
/// Clears a graph from this store. /// Clears a graph from this store.
@ -510,6 +513,8 @@ impl SledStore {
/// Removes a graph from this store. /// Removes a graph from this store.
/// ///
/// Returns `true` if the graph was in the store and has been removed.
///
/// Usage example: /// Usage example:
/// ``` /// ```
/// use oxigraph::SledStore; /// use oxigraph::SledStore;
@ -529,12 +534,11 @@ impl SledStore {
pub fn remove_named_graph<'a>( pub fn remove_named_graph<'a>(
&self, &self,
graph_name: impl Into<NamedOrBlankNodeRef<'a>>, graph_name: impl Into<NamedOrBlankNodeRef<'a>>,
) -> Result<(), io::Error> { ) -> Result<bool, io::Error> {
if let Some(graph_name) = self.get_encoded_named_or_blank_node(graph_name.into())? { if let Some(graph_name) = self.get_encoded_named_or_blank_node(graph_name.into())? {
let mut this = self; self.storage.remove_named_graph(graph_name)
this.remove_encoded_named_graph(graph_name)
} else { } else {
Ok(()) Ok(false)
} }
} }
@ -580,12 +584,7 @@ impl StrLookup for SledStore {
} }
fn get_str_id(&self, value: &str) -> Result<Option<StrHash>, io::Error> { fn get_str_id(&self, value: &str) -> Result<Option<StrHash>, io::Error> {
let key = StrHash::new(value); self.storage.get_str_id(value)
Ok(if self.storage.contains_str(key)? {
Some(key)
} else {
None
})
} }
} }
@ -614,7 +613,7 @@ impl ReadableEncodedStore for SledStore {
} }
impl<'a> StrContainer for &'a SledStore { impl<'a> StrContainer for &'a SledStore {
fn insert_str(&mut 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)?;
Ok(key) Ok(key)
@ -623,15 +622,18 @@ impl<'a> StrContainer for &'a SledStore {
impl<'a> WritableEncodedStore for &'a SledStore { impl<'a> WritableEncodedStore for &'a SledStore {
fn insert_encoded(&mut self, quad: &EncodedQuad) -> Result<(), io::Error> { fn insert_encoded(&mut self, quad: &EncodedQuad) -> Result<(), io::Error> {
self.storage.insert(quad) self.storage.insert(quad)?;
Ok(())
} }
fn remove_encoded(&mut self, quad: &EncodedQuad) -> Result<(), io::Error> { fn remove_encoded(&mut self, quad: &EncodedQuad) -> Result<(), io::Error> {
self.storage.remove(quad) self.storage.remove(quad)?;
Ok(())
} }
fn insert_encoded_named_graph(&mut self, graph_name: EncodedTerm) -> Result<(), io::Error> { fn insert_encoded_named_graph(&mut self, graph_name: EncodedTerm) -> Result<(), io::Error> {
self.storage.insert_named_graph(graph_name) self.storage.insert_named_graph(graph_name)?;
Ok(())
} }
fn clear_encoded_graph(&mut self, graph_name: EncodedTerm) -> Result<(), io::Error> { fn clear_encoded_graph(&mut self, graph_name: EncodedTerm) -> Result<(), io::Error> {
@ -639,7 +641,8 @@ impl<'a> WritableEncodedStore for &'a SledStore {
} }
fn remove_encoded_named_graph(&mut self, graph_name: EncodedTerm) -> Result<(), io::Error> { fn remove_encoded_named_graph(&mut self, graph_name: EncodedTerm) -> Result<(), io::Error> {
self.storage.remove_named_graph(graph_name) self.storage.remove_named_graph(graph_name)?;
Ok(())
} }
fn clear(&mut self) -> Result<(), io::Error> { fn clear(&mut self) -> Result<(), io::Error> {
@ -747,25 +750,27 @@ impl SledTransaction<'_> {
} }
/// Adds a quad to this store during the transaction. /// Adds a quad to this store during the transaction.
///
/// Returns `true` if the quad was not already in the store.
pub fn insert<'a>( pub fn insert<'a>(
&self, &self,
quad: impl Into<QuadRef<'a>>, quad: impl Into<QuadRef<'a>>,
) -> Result<(), SledUnabortableTransactionError> { ) -> Result<bool, SledUnabortableTransactionError> {
let mut this = self; let quad = self.encode_quad(quad.into())?;
let quad = this.encode_quad(quad.into())?; self.storage.insert(&quad)
this.insert_encoded(&quad)
} }
/// Removes a quad from this store during the transaction. /// Removes a quad from this store during the transaction.
///
/// Returns `true` if the quad was in the store and has been removed.
pub fn remove<'a>( pub fn remove<'a>(
&self, &self,
quad: impl Into<QuadRef<'a>>, quad: impl Into<QuadRef<'a>>,
) -> Result<(), SledUnabortableTransactionError> { ) -> Result<bool, SledUnabortableTransactionError> {
let mut this = self; if let Some(quad) = self.get_encoded_quad(quad.into())? {
if let Some(quad) = this.get_encoded_quad(quad.into())? { self.storage.remove(&quad)
this.remove_encoded(&quad)
} else { } else {
Ok(()) Ok(false)
} }
} }
} }
@ -780,17 +785,12 @@ impl<'a> StrLookup for &'a SledTransaction<'a> {
} }
fn get_str_id(&self, value: &str) -> Result<Option<StrHash>, SledUnabortableTransactionError> { fn get_str_id(&self, value: &str) -> Result<Option<StrHash>, SledUnabortableTransactionError> {
let key = StrHash::new(value); self.storage.get_str_id(value)
Ok(if self.storage.contains_str(key)? {
Some(key)
} else {
None
})
} }
} }
impl<'a> StrContainer for &'a SledTransaction<'a> { impl<'a> StrContainer for &'a SledTransaction<'a> {
fn insert_str(&mut self, value: &str) -> Result<StrHash, SledUnabortableTransactionError> { fn insert_str(&self, value: &str) -> Result<StrHash, SledUnabortableTransactionError> {
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)
@ -802,21 +802,24 @@ impl<'a> WritableEncodedStore for &'a SledTransaction<'a> {
&mut self, &mut self,
quad: &EncodedQuad, quad: &EncodedQuad,
) -> Result<(), SledUnabortableTransactionError> { ) -> Result<(), SledUnabortableTransactionError> {
self.storage.insert(quad) self.storage.insert(quad)?;
Ok(())
} }
fn remove_encoded( fn remove_encoded(
&mut self, &mut self,
quad: &EncodedQuad, quad: &EncodedQuad,
) -> Result<(), SledUnabortableTransactionError> { ) -> Result<(), SledUnabortableTransactionError> {
self.storage.remove(quad) self.storage.remove(quad)?;
Ok(())
} }
fn insert_encoded_named_graph( fn insert_encoded_named_graph(
&mut self, &mut self,
graph_name: EncodedTerm, graph_name: EncodedTerm,
) -> Result<(), SledUnabortableTransactionError> { ) -> Result<(), SledUnabortableTransactionError> {
self.storage.insert_named_graph(graph_name) self.storage.insert_named_graph(graph_name)?;
Ok(())
} }
fn clear_encoded_graph( fn clear_encoded_graph(
@ -938,16 +941,20 @@ fn store() -> Result<(), io::Error> {
let store = SledStore::new()?; let store = SledStore::new()?;
for t in &default_quads { for t in &default_quads {
store.insert(t)?; assert!(store.insert(t)?);
} }
let result: Result<_, SledTransactionError<io::Error>> = store.transaction(|t| { let result: Result<_, SledTransactionError<io::Error>> = store.transaction(|t| {
t.remove(&default_quad)?; assert!(t.remove(&default_quad)?);
t.insert(&named_quad)?; assert_eq!(t.remove(&default_quad)?, false);
t.insert(&default_quad)?; assert!(t.insert(&named_quad)?);
assert_eq!(t.insert(&named_quad)?, false);
assert!(t.insert(&default_quad)?);
assert_eq!(t.insert(&default_quad)?, false);
Ok(()) Ok(())
}); });
result?; result?;
assert_eq!(store.insert(&default_quad)?, false);
assert_eq!(store.len(), 4); assert_eq!(store.len(), 4);
assert_eq!(store.iter().collect::<Result<Vec<_>, _>>()?, all_quads); assert_eq!(store.iter().collect::<Result<Vec<_>, _>>()?, all_quads);

@ -444,12 +444,14 @@ impl Storage {
} }
} }
pub fn insert(&self, quad: &EncodedQuad) -> Result<(), io::Error> { pub fn insert(&self, quad: &EncodedQuad) -> Result<bool, 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() {
write_spo_quad(&mut buffer, quad); write_spo_quad(&mut buffer, quad);
self.dspo.insert(buffer.as_slice(), &[])?; let is_new = self.dspo.insert(buffer.as_slice(), &[])?.is_none();
if is_new {
buffer.clear(); buffer.clear();
write_pos_quad(&mut buffer, quad); write_pos_quad(&mut buffer, quad);
@ -459,9 +461,13 @@ impl Storage {
write_osp_quad(&mut buffer, quad); write_osp_quad(&mut buffer, quad);
self.dosp.insert(buffer.as_slice(), &[])?; self.dosp.insert(buffer.as_slice(), &[])?;
buffer.clear(); buffer.clear();
}
Ok(is_new)
} else { } else {
write_spog_quad(&mut buffer, quad); write_spog_quad(&mut buffer, quad);
self.spog.insert(buffer.as_slice(), &[])?; let is_new = self.spog.insert(buffer.as_slice(), &[])?.is_none();
if is_new {
buffer.clear(); buffer.clear();
write_posg_quad(&mut buffer, quad); write_posg_quad(&mut buffer, quad);
@ -489,15 +495,18 @@ impl Storage {
buffer.clear(); buffer.clear();
} }
Ok(()) Ok(is_new)
}
} }
pub fn remove(&self, quad: &EncodedQuad) -> Result<(), io::Error> { pub fn remove(&self, quad: &EncodedQuad) -> Result<bool, 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() {
write_spo_quad(&mut buffer, quad); write_spo_quad(&mut buffer, quad);
self.dspo.remove(buffer.as_slice())?; let is_present = self.dspo.remove(buffer.as_slice())?.is_some();
if is_present {
buffer.clear(); buffer.clear();
write_pos_quad(&mut buffer, quad); write_pos_quad(&mut buffer, quad);
@ -507,9 +516,14 @@ impl Storage {
write_osp_quad(&mut buffer, quad); write_osp_quad(&mut buffer, quad);
self.dosp.remove(buffer.as_slice())?; self.dosp.remove(buffer.as_slice())?;
buffer.clear(); buffer.clear();
}
Ok(is_present)
} else { } else {
write_spog_quad(&mut buffer, quad); write_spog_quad(&mut buffer, quad);
self.spog.remove(buffer.as_slice())?; let is_present = self.spog.remove(buffer.as_slice())?.is_some();
if is_present {
buffer.clear(); buffer.clear();
write_posg_quad(&mut buffer, quad); write_posg_quad(&mut buffer, quad);
@ -533,12 +547,12 @@ impl Storage {
buffer.clear(); buffer.clear();
} }
Ok(()) Ok(is_present)
}
} }
pub fn insert_named_graph(&self, graph_name: EncodedTerm) -> Result<(), io::Error> { pub fn insert_named_graph(&self, graph_name: EncodedTerm) -> Result<bool, io::Error> {
self.graphs.insert(&encode_term(graph_name), &[])?; Ok(self.graphs.insert(&encode_term(graph_name), &[])?.is_none())
Ok(())
} }
pub fn clear_graph(&self, graph_name: EncodedTerm) -> Result<(), io::Error> { pub fn clear_graph(&self, graph_name: EncodedTerm) -> Result<(), io::Error> {
@ -554,12 +568,11 @@ impl Storage {
Ok(()) Ok(())
} }
pub fn remove_named_graph(&self, graph_name: EncodedTerm) -> Result<(), io::Error> { pub fn remove_named_graph(&self, graph_name: EncodedTerm) -> Result<bool, 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?)?;
} }
self.graphs.remove(&encode_term(graph_name))?; Ok(self.graphs.remove(&encode_term(graph_name))?.is_some())
Ok(())
} }
pub fn clear(&self) -> Result<(), io::Error> { pub fn clear(&self) -> Result<(), io::Error> {
@ -589,9 +602,8 @@ impl Storage {
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<(), io::Error> { pub fn insert_str(&self, key: StrHash, value: &str) -> Result<bool, io::Error> {
self.id2str.insert(key.to_be_bytes(), value)?; Ok(self.id2str.insert(key.to_be_bytes(), value)?.is_none())
Ok(())
} }
} }
@ -676,12 +688,14 @@ pub struct StorageTransaction<'a> {
} }
impl<'a> StorageTransaction<'a> { impl<'a> StorageTransaction<'a> {
pub fn insert(&self, quad: &EncodedQuad) -> Result<(), SledUnabortableTransactionError> { pub fn insert(&self, quad: &EncodedQuad) -> Result<bool, SledUnabortableTransactionError> {
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() {
write_spo_quad(&mut buffer, quad); write_spo_quad(&mut buffer, quad);
self.dspo.insert(buffer.as_slice(), &[])?; let is_new = self.dspo.insert(buffer.as_slice(), &[])?.is_none();
if is_new {
buffer.clear(); buffer.clear();
write_pos_quad(&mut buffer, quad); write_pos_quad(&mut buffer, quad);
@ -691,9 +705,14 @@ impl<'a> StorageTransaction<'a> {
write_osp_quad(&mut buffer, quad); write_osp_quad(&mut buffer, quad);
self.dosp.insert(buffer.as_slice(), &[])?; self.dosp.insert(buffer.as_slice(), &[])?;
buffer.clear(); buffer.clear();
}
Ok(is_new)
} else { } else {
write_spog_quad(&mut buffer, quad); write_spog_quad(&mut buffer, quad);
self.spog.insert(buffer.as_slice(), &[])?; let is_new = self.spog.insert(buffer.as_slice(), &[])?.is_none();
if is_new {
buffer.clear(); buffer.clear();
write_posg_quad(&mut buffer, quad); write_posg_quad(&mut buffer, quad);
@ -721,15 +740,18 @@ impl<'a> StorageTransaction<'a> {
buffer.clear(); buffer.clear();
} }
Ok(()) Ok(is_new)
}
} }
pub fn remove(&self, quad: &EncodedQuad) -> Result<(), SledUnabortableTransactionError> { pub fn remove(&self, quad: &EncodedQuad) -> Result<bool, SledUnabortableTransactionError> {
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() {
write_spo_quad(&mut buffer, quad); write_spo_quad(&mut buffer, quad);
self.dspo.remove(buffer.as_slice())?; let is_present = self.dspo.remove(buffer.as_slice())?.is_some();
if is_present {
buffer.clear(); buffer.clear();
write_pos_quad(&mut buffer, quad); write_pos_quad(&mut buffer, quad);
@ -739,9 +761,14 @@ impl<'a> StorageTransaction<'a> {
write_osp_quad(&mut buffer, quad); write_osp_quad(&mut buffer, quad);
self.dosp.remove(buffer.as_slice())?; self.dosp.remove(buffer.as_slice())?;
buffer.clear(); buffer.clear();
}
Ok(is_present)
} else { } else {
write_spog_quad(&mut buffer, quad); write_spog_quad(&mut buffer, quad);
self.spog.remove(buffer.as_slice())?; let is_present = self.spog.remove(buffer.as_slice())?.is_some();
if is_present {
buffer.clear(); buffer.clear();
write_posg_quad(&mut buffer, quad); write_posg_quad(&mut buffer, quad);
@ -765,15 +792,15 @@ impl<'a> StorageTransaction<'a> {
buffer.clear(); buffer.clear();
} }
Ok(()) Ok(is_present)
}
} }
pub fn insert_named_graph( pub fn insert_named_graph(
&self, &self,
graph_name: EncodedTerm, graph_name: EncodedTerm,
) -> Result<(), SledUnabortableTransactionError> { ) -> Result<bool, SledUnabortableTransactionError> {
self.graphs.insert(encode_term(graph_name), &[])?; Ok(self.graphs.insert(encode_term(graph_name), &[])?.is_none())
Ok(())
} }
pub fn get_str(&self, key: StrHash) -> Result<Option<String>, SledUnabortableTransactionError> { pub fn get_str(&self, key: StrHash) -> Result<Option<String>, SledUnabortableTransactionError> {
@ -792,9 +819,8 @@ impl<'a> StorageTransaction<'a> {
&self, &self,
key: StrHash, key: StrHash,
value: &str, value: &str,
) -> Result<(), SledUnabortableTransactionError> { ) -> Result<bool, SledUnabortableTransactionError> {
self.id2str.insert(&key.to_be_bytes(), value)?; Ok(self.id2str.insert(&key.to_be_bytes(), value)?.is_none())
Ok(())
} }
} }
@ -949,3 +975,57 @@ impl<T> From<SledConflictableTransactionError<T>> for ConflictableTransactionErr
} }
} }
} }
impl StrEncodingAware for Storage {
type Error = io::Error;
}
impl StrLookup for Storage {
fn get_str(&self, id: StrHash) -> Result<Option<String>, io::Error> {
self.get_str(id)
}
fn get_str_id(&self, value: &str) -> Result<Option<StrHash>, io::Error> {
let key = StrHash::new(value);
Ok(if self.contains_str(key)? {
Some(key)
} else {
None
})
}
}
impl StrContainer for Storage {
fn insert_str(&self, value: &str) -> Result<StrHash, io::Error> {
let key = StrHash::new(value);
self.insert_str(key, value)?;
Ok(key)
}
}
impl<'a> StrEncodingAware for StorageTransaction<'a> {
type Error = SledUnabortableTransactionError;
}
impl<'a> StrLookup for StorageTransaction<'a> {
fn get_str(&self, id: StrHash) -> Result<Option<String>, SledUnabortableTransactionError> {
self.get_str(id)
}
fn get_str_id(&self, value: &str) -> Result<Option<StrHash>, SledUnabortableTransactionError> {
let key = StrHash::new(value);
Ok(if self.contains_str(key)? {
Some(key)
} else {
None
})
}
}
impl<'a> StrContainer for StorageTransaction<'a> {
fn insert_str(&self, value: &str) -> Result<StrHash, SledUnabortableTransactionError> {
let key = StrHash::new(value);
self.insert_str(key, value)?;
Ok(key)
}
}

@ -60,7 +60,8 @@ impl PyStore {
/// [<Quad subject=<NamedNode value=http://example.com> predicate=<NamedNode value=http://example.com/p> object=<Literal value=1 datatype=<NamedNode value=http://www.w3.org/2001/XMLSchema#string>> graph_name=<NamedNode value=http://example.com/g>>] /// [<Quad subject=<NamedNode value=http://example.com> predicate=<NamedNode value=http://example.com/p> object=<Literal value=1 datatype=<NamedNode value=http://www.w3.org/2001/XMLSchema#string>> graph_name=<NamedNode value=http://example.com/g>>]
#[text_signature = "($self, quad)"] #[text_signature = "($self, quad)"]
fn add(&self, quad: &PyQuad) -> PyResult<()> { fn add(&self, quad: &PyQuad) -> PyResult<()> {
self.inner.insert(quad).map_err(map_io_err) self.inner.insert(quad).map_err(map_io_err)?;
Ok(())
} }
/// Removes a quad from the store /// Removes a quad from the store
@ -77,7 +78,8 @@ impl PyStore {
/// [] /// []
#[text_signature = "($self, quad)"] #[text_signature = "($self, quad)"]
fn remove(&self, quad: &PyQuad) -> PyResult<()> { fn remove(&self, quad: &PyQuad) -> PyResult<()> {
self.inner.remove(quad).map_err(map_io_err) self.inner.remove(quad).map_err(map_io_err)?;
Ok(())
} }
/// Looks for the quads matching a given pattern /// Looks for the quads matching a given pattern
@ -383,10 +385,12 @@ impl PyStore {
PyGraphNameRef::DefaultGraph => Ok(()), PyGraphNameRef::DefaultGraph => Ok(()),
PyGraphNameRef::NamedNode(graph_name) => self PyGraphNameRef::NamedNode(graph_name) => self
.inner .inner
.insert_named_graph(&PyNamedOrBlankNodeRef::NamedNode(graph_name)), .insert_named_graph(&PyNamedOrBlankNodeRef::NamedNode(graph_name))
.map(|_| ()),
PyGraphNameRef::BlankNode(graph_name) => self PyGraphNameRef::BlankNode(graph_name) => self
.inner .inner
.insert_named_graph(&PyNamedOrBlankNodeRef::BlankNode(graph_name)), .insert_named_graph(&PyNamedOrBlankNodeRef::BlankNode(graph_name))
.map(|_| ()),
} }
.map_err(map_io_err) .map_err(map_io_err)
} }
@ -410,12 +414,15 @@ impl PyStore {
PyGraphNameRef::DefaultGraph => self.inner.clear_graph(GraphNameRef::DefaultGraph), PyGraphNameRef::DefaultGraph => self.inner.clear_graph(GraphNameRef::DefaultGraph),
PyGraphNameRef::NamedNode(graph_name) => self PyGraphNameRef::NamedNode(graph_name) => self
.inner .inner
.remove_named_graph(&PyNamedOrBlankNodeRef::NamedNode(graph_name)), .remove_named_graph(&PyNamedOrBlankNodeRef::NamedNode(graph_name))
.map(|_| ()),
PyGraphNameRef::BlankNode(graph_name) => self PyGraphNameRef::BlankNode(graph_name) => self
.inner .inner
.remove_named_graph(&PyNamedOrBlankNodeRef::BlankNode(graph_name)), .remove_named_graph(&PyNamedOrBlankNodeRef::BlankNode(graph_name))
.map(|_| ()),
} }
.map_err(map_io_err) .map_err(map_io_err)?;
Ok(())
} }
} }

Loading…
Cancel
Save