StrContainer does not need to be mutable

pull/171/head
Tpt 4 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. 346
      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> {
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())? {
Ok(hash)
} else {

@ -1377,7 +1377,7 @@ where
} else {
None
}?;
let mut encoder = self.dataset.as_ref();
let encoder = self.dataset.as_ref();
encoder
.encode_literal(LiteralRef::new_typed_literal(
&value,
@ -1823,7 +1823,7 @@ where
) -> EncodedTuplesIterator {
let eval = self.clone();
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());
for (variable, term) in solution?.iter() {
put_variable_value(

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

@ -502,7 +502,7 @@ pub(crate) trait StrLookup: 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)
@ -744,17 +744,11 @@ impl<S: StrLookup> ReadEncoder for S {
/// Encodes a term and insert strings if needed
pub(crate) trait WriteEncoder: StrEncodingAware {
fn encode_named_node(
&mut self,
named_node: NamedNodeRef<'_>,
) -> Result<EncodedTerm, Self::Error> {
fn encode_named_node(&self, named_node: NamedNodeRef<'_>) -> Result<EncodedTerm, Self::Error> {
self.encode_rio_named_node(named_node.into())
}
fn encode_blank_node(
&mut self,
blank_node: BlankNodeRef<'_>,
) -> Result<EncodedTerm, Self::Error> {
fn encode_blank_node(&self, blank_node: BlankNodeRef<'_>) -> Result<EncodedTerm, Self::Error> {
Ok(if let Some(id) = blank_node.id() {
EncodedTerm::NumericalBlankNode { id }
} 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())
}
fn encode_named_or_blank_node(
&mut self,
&self,
term: NamedOrBlankNodeRef<'_>,
) -> Result<EncodedTerm, Self::Error> {
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 {
TermRef::NamedNode(named_node) => self.encode_named_node(named_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 {
GraphNameRef::NamedNode(named_node) => self.encode_named_node(named_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 {
subject: self.encode_named_or_blank_node(quad.subject)?,
predicate: self.encode_named_node(quad.predicate)?,
@ -809,7 +803,7 @@ pub(crate) trait WriteEncoder: StrEncodingAware {
}
fn encode_triple_in_graph(
&mut self,
&self,
triple: TripleRef<'_>,
graph_name: EncodedTerm,
) -> Result<EncodedQuad, Self::Error> {
@ -822,7 +816,7 @@ pub(crate) trait WriteEncoder: StrEncodingAware {
}
fn encode_rio_named_node(
&mut self,
&self,
named_node: rio::NamedNode<'_>,
) -> Result<EncodedTerm, Self::Error> {
Ok(EncodedTerm::NamedNode {
@ -831,7 +825,7 @@ pub(crate) trait WriteEncoder: StrEncodingAware {
}
fn encode_rio_blank_node(
&mut self,
&self,
blank_node: rio::BlankNode<'_>,
bnodes_map: &mut HashMap<String, u128>,
) -> Result<EncodedTerm, Self::Error> {
@ -843,10 +837,7 @@ pub(crate) trait WriteEncoder: StrEncodingAware {
EncodedTerm::NumericalBlankNode { id }
})
}
fn encode_rio_literal(
&mut self,
literal: rio::Literal<'_>,
) -> Result<EncodedTerm, Self::Error> {
fn encode_rio_literal(&self, literal: rio::Literal<'_>) -> Result<EncodedTerm, Self::Error> {
Ok(match literal {
rio::Literal::Simple { 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(
&mut self,
&self,
term: rio::NamedOrBlankNode<'_>,
bnodes_map: &mut HashMap<String, u128>,
) -> Result<EncodedTerm, Self::Error> {
@ -962,7 +953,7 @@ pub(crate) trait WriteEncoder: StrEncodingAware {
}
fn encode_rio_term(
&mut self,
&self,
term: rio::Term<'_>,
bnodes_map: &mut HashMap<String, u128>,
) -> Result<EncodedTerm, Self::Error> {
@ -974,7 +965,7 @@ pub(crate) trait WriteEncoder: StrEncodingAware {
}
fn encode_rio_quad(
&mut self,
&self,
quad: rio::Quad<'_>,
bnodes_map: &mut HashMap<String, u128>,
) -> Result<EncodedQuad, Self::Error> {
@ -990,7 +981,7 @@ pub(crate) trait WriteEncoder: StrEncodingAware {
}
fn encode_rio_triple_in_graph(
&mut self,
&self,
triple: rio::Triple<'_>,
graph_name: EncodedTerm,
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 {
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)
}
}

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

@ -444,101 +444,115 @@ 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);
if quad.graph_name.is_default_graph() {
write_spo_quad(&mut buffer, quad);
self.dspo.insert(buffer.as_slice(), &[])?;
buffer.clear();
let is_new = self.dspo.insert(buffer.as_slice(), &[])?.is_none();
write_pos_quad(&mut buffer, quad);
self.dpos.insert(buffer.as_slice(), &[])?;
buffer.clear();
if is_new {
buffer.clear();
write_osp_quad(&mut buffer, quad);
self.dosp.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_pos_quad(&mut buffer, quad);
self.dpos.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_osp_quad(&mut buffer, quad);
self.dosp.insert(buffer.as_slice(), &[])?;
buffer.clear();
}
Ok(is_new)
} else {
write_spog_quad(&mut buffer, quad);
self.spog.insert(buffer.as_slice(), &[])?;
buffer.clear();
let is_new = self.spog.insert(buffer.as_slice(), &[])?.is_none();
if is_new {
buffer.clear();
write_posg_quad(&mut buffer, quad);
self.posg.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_posg_quad(&mut buffer, quad);
self.posg.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_ospg_quad(&mut buffer, quad);
self.ospg.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_ospg_quad(&mut buffer, quad);
self.ospg.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_gspo_quad(&mut buffer, quad);
self.gspo.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_gspo_quad(&mut buffer, quad);
self.gspo.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_gpos_quad(&mut buffer, quad);
self.gpos.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_gpos_quad(&mut buffer, quad);
self.gpos.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_gosp_quad(&mut buffer, quad);
self.gosp.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_gosp_quad(&mut buffer, quad);
self.gosp.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_term(&mut buffer, quad.graph_name);
self.graphs.insert(&buffer, &[])?;
buffer.clear();
}
write_term(&mut buffer, quad.graph_name);
self.graphs.insert(&buffer, &[])?;
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);
if quad.graph_name.is_default_graph() {
write_spo_quad(&mut buffer, quad);
self.dspo.remove(buffer.as_slice())?;
buffer.clear();
let is_present = self.dspo.remove(buffer.as_slice())?.is_some();
if is_present {
buffer.clear();
write_pos_quad(&mut buffer, quad);
self.dpos.remove(buffer.as_slice())?;
buffer.clear();
write_pos_quad(&mut buffer, quad);
self.dpos.remove(buffer.as_slice())?;
buffer.clear();
write_osp_quad(&mut buffer, quad);
self.dosp.remove(buffer.as_slice())?;
buffer.clear();
write_osp_quad(&mut buffer, quad);
self.dosp.remove(buffer.as_slice())?;
buffer.clear();
}
Ok(is_present)
} else {
write_spog_quad(&mut buffer, quad);
self.spog.remove(buffer.as_slice())?;
buffer.clear();
let is_present = self.spog.remove(buffer.as_slice())?.is_some();
write_posg_quad(&mut buffer, quad);
self.posg.remove(buffer.as_slice())?;
buffer.clear();
if is_present {
buffer.clear();
write_ospg_quad(&mut buffer, quad);
self.ospg.remove(buffer.as_slice())?;
buffer.clear();
write_posg_quad(&mut buffer, quad);
self.posg.remove(buffer.as_slice())?;
buffer.clear();
write_gspo_quad(&mut buffer, quad);
self.gspo.remove(buffer.as_slice())?;
buffer.clear();
write_ospg_quad(&mut buffer, quad);
self.ospg.remove(buffer.as_slice())?;
buffer.clear();
write_gpos_quad(&mut buffer, quad);
self.gpos.remove(buffer.as_slice())?;
buffer.clear();
write_gspo_quad(&mut buffer, quad);
self.gspo.remove(buffer.as_slice())?;
buffer.clear();
write_gosp_quad(&mut buffer, quad);
self.gosp.remove(buffer.as_slice())?;
buffer.clear();
}
write_gpos_quad(&mut buffer, quad);
self.gpos.remove(buffer.as_slice())?;
buffer.clear();
Ok(())
write_gosp_quad(&mut buffer, quad);
self.gosp.remove(buffer.as_slice())?;
buffer.clear();
}
Ok(is_present)
}
}
pub fn insert_named_graph(&self, graph_name: EncodedTerm) -> Result<(), io::Error> {
self.graphs.insert(&encode_term(graph_name), &[])?;
Ok(())
pub fn insert_named_graph(&self, graph_name: EncodedTerm) -> Result<bool, io::Error> {
Ok(self.graphs.insert(&encode_term(graph_name), &[])?.is_none())
}
pub fn clear_graph(&self, graph_name: EncodedTerm) -> Result<(), io::Error> {
@ -554,12 +568,11 @@ impl Storage {
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) {
self.remove(&quad?)?;
}
self.graphs.remove(&encode_term(graph_name))?;
Ok(())
Ok(self.graphs.remove(&encode_term(graph_name))?.is_some())
}
pub fn clear(&self) -> Result<(), io::Error> {
@ -589,9 +602,8 @@ impl Storage {
Ok(self.id2str.contains_key(key.to_be_bytes())?)
}
pub fn insert_str(&self, key: StrHash, value: &str) -> Result<(), io::Error> {
self.id2str.insert(key.to_be_bytes(), value)?;
Ok(())
pub fn insert_str(&self, key: StrHash, value: &str) -> Result<bool, io::Error> {
Ok(self.id2str.insert(key.to_be_bytes(), value)?.is_none())
}
}
@ -676,104 +688,119 @@ pub struct 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);
if quad.graph_name.is_default_graph() {
write_spo_quad(&mut buffer, quad);
self.dspo.insert(buffer.as_slice(), &[])?;
buffer.clear();
let is_new = self.dspo.insert(buffer.as_slice(), &[])?.is_none();
if is_new {
buffer.clear();
write_pos_quad(&mut buffer, quad);
self.dpos.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_pos_quad(&mut buffer, quad);
self.dpos.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_osp_quad(&mut buffer, quad);
self.dosp.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_osp_quad(&mut buffer, quad);
self.dosp.insert(buffer.as_slice(), &[])?;
buffer.clear();
}
Ok(is_new)
} else {
write_spog_quad(&mut buffer, quad);
self.spog.insert(buffer.as_slice(), &[])?;
buffer.clear();
let is_new = self.spog.insert(buffer.as_slice(), &[])?.is_none();
write_posg_quad(&mut buffer, quad);
self.posg.insert(buffer.as_slice(), &[])?;
buffer.clear();
if is_new {
buffer.clear();
write_ospg_quad(&mut buffer, quad);
self.ospg.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_posg_quad(&mut buffer, quad);
self.posg.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_gspo_quad(&mut buffer, quad);
self.gspo.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_ospg_quad(&mut buffer, quad);
self.ospg.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_gpos_quad(&mut buffer, quad);
self.gpos.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_gspo_quad(&mut buffer, quad);
self.gspo.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_gosp_quad(&mut buffer, quad);
self.gosp.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_gpos_quad(&mut buffer, quad);
self.gpos.insert(buffer.as_slice(), &[])?;
buffer.clear();
write_term(&mut buffer, quad.graph_name);
self.graphs.insert(buffer.as_slice(), &[])?;
buffer.clear();
}
write_gosp_quad(&mut buffer, quad);
self.gosp.insert(buffer.as_slice(), &[])?;
buffer.clear();
Ok(())
write_term(&mut buffer, quad.graph_name);
self.graphs.insert(buffer.as_slice(), &[])?;
buffer.clear();
}
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);
if quad.graph_name.is_default_graph() {
write_spo_quad(&mut buffer, quad);
self.dspo.remove(buffer.as_slice())?;
buffer.clear();
let is_present = self.dspo.remove(buffer.as_slice())?.is_some();
write_pos_quad(&mut buffer, quad);
self.dpos.remove(buffer.as_slice())?;
buffer.clear();
if is_present {
buffer.clear();
write_osp_quad(&mut buffer, quad);
self.dosp.remove(buffer.as_slice())?;
buffer.clear();
write_pos_quad(&mut buffer, quad);
self.dpos.remove(buffer.as_slice())?;
buffer.clear();
write_osp_quad(&mut buffer, quad);
self.dosp.remove(buffer.as_slice())?;
buffer.clear();
}
Ok(is_present)
} else {
write_spog_quad(&mut buffer, quad);
self.spog.remove(buffer.as_slice())?;
buffer.clear();
let is_present = self.spog.remove(buffer.as_slice())?.is_some();
write_posg_quad(&mut buffer, quad);
self.posg.remove(buffer.as_slice())?;
buffer.clear();
if is_present {
buffer.clear();
write_ospg_quad(&mut buffer, quad);
self.ospg.remove(buffer.as_slice())?;
buffer.clear();
write_posg_quad(&mut buffer, quad);
self.posg.remove(buffer.as_slice())?;
buffer.clear();
write_gspo_quad(&mut buffer, quad);
self.gspo.remove(buffer.as_slice())?;
buffer.clear();
write_ospg_quad(&mut buffer, quad);
self.ospg.remove(buffer.as_slice())?;
buffer.clear();
write_gpos_quad(&mut buffer, quad);
self.gpos.remove(buffer.as_slice())?;
buffer.clear();
write_gspo_quad(&mut buffer, quad);
self.gspo.remove(buffer.as_slice())?;
buffer.clear();
write_gosp_quad(&mut buffer, quad);
self.gosp.remove(buffer.as_slice())?;
buffer.clear();
}
write_gpos_quad(&mut buffer, quad);
self.gpos.remove(buffer.as_slice())?;
buffer.clear();
Ok(())
write_gosp_quad(&mut buffer, quad);
self.gosp.remove(buffer.as_slice())?;
buffer.clear();
}
Ok(is_present)
}
}
pub fn insert_named_graph(
&self,
graph_name: EncodedTerm,
) -> Result<(), SledUnabortableTransactionError> {
self.graphs.insert(encode_term(graph_name), &[])?;
Ok(())
) -> Result<bool, SledUnabortableTransactionError> {
Ok(self.graphs.insert(encode_term(graph_name), &[])?.is_none())
}
pub fn get_str(&self, key: StrHash) -> Result<Option<String>, SledUnabortableTransactionError> {
@ -792,9 +819,8 @@ impl<'a> StorageTransaction<'a> {
&self,
key: StrHash,
value: &str,
) -> Result<(), SledUnabortableTransactionError> {
self.id2str.insert(&key.to_be_bytes(), value)?;
Ok(())
) -> Result<bool, SledUnabortableTransactionError> {
Ok(self.id2str.insert(&key.to_be_bytes(), value)?.is_none())
}
}
@ -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>>]
#[text_signature = "($self, quad)"]
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
@ -77,7 +78,8 @@ impl PyStore {
/// []
#[text_signature = "($self, quad)"]
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
@ -383,10 +385,12 @@ impl PyStore {
PyGraphNameRef::DefaultGraph => Ok(()),
PyGraphNameRef::NamedNode(graph_name) => self
.inner
.insert_named_graph(&PyNamedOrBlankNodeRef::NamedNode(graph_name)),
.insert_named_graph(&PyNamedOrBlankNodeRef::NamedNode(graph_name))
.map(|_| ()),
PyGraphNameRef::BlankNode(graph_name) => self
.inner
.insert_named_graph(&PyNamedOrBlankNodeRef::BlankNode(graph_name)),
.insert_named_graph(&PyNamedOrBlankNodeRef::BlankNode(graph_name))
.map(|_| ()),
}
.map_err(map_io_err)
}
@ -410,12 +414,15 @@ impl PyStore {
PyGraphNameRef::DefaultGraph => self.inner.clear_graph(GraphNameRef::DefaultGraph),
PyGraphNameRef::NamedNode(graph_name) => self
.inner
.remove_named_graph(&PyNamedOrBlankNodeRef::NamedNode(graph_name)),
.remove_named_graph(&PyNamedOrBlankNodeRef::NamedNode(graph_name))
.map(|_| ()),
PyGraphNameRef::BlankNode(graph_name) => self
.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