Makes term encoding not fail if the string is not stored

pull/171/head
Tpt 4 years ago
parent 68aab2563c
commit aa7a23b94d
  1. 29
      lib/src/sparql/dataset.rs
  2. 116
      lib/src/sparql/update.rs
  3. 5
      lib/src/storage/binary_encoder.rs
  4. 197
      lib/src/storage/numeric_encoder.rs
  5. 152
      lib/src/store.rs

@ -1,7 +1,8 @@
use crate::sparql::algebra::QueryDataset; use crate::sparql::algebra::QueryDataset;
use crate::sparql::EvaluationError; use crate::sparql::EvaluationError;
use crate::storage::numeric_encoder::{ use crate::storage::numeric_encoder::{
EncodedQuad, EncodedTerm, ReadEncoder, StrContainer, StrHash, StrLookup, get_encoded_graph_name, get_encoded_named_or_blank_node, EncodedQuad, EncodedTerm,
StrContainer, StrHash, StrLookup,
}; };
use crate::storage::Storage; use crate::storage::Storage;
use std::cell::RefCell; use std::cell::RefCell;
@ -18,28 +19,18 @@ pub(crate) struct DatasetView {
impl DatasetView { impl DatasetView {
pub fn new(storage: Storage, dataset: &QueryDataset) -> Result<Self, EvaluationError> { pub fn new(storage: Storage, dataset: &QueryDataset) -> Result<Self, EvaluationError> {
let dataset = EncodedDatasetSpec { let dataset = EncodedDatasetSpec {
default: dataset default: dataset.default_graph_graphs().map(|graphs| {
.default_graph_graphs()
.map(|graphs| {
graphs graphs
.iter() .iter()
.flat_map(|g| storage.get_encoded_graph_name(g.as_ref()).transpose()) .map(|g| get_encoded_graph_name(g.as_ref()))
.collect::<Result<Vec<_>, _>>() .collect::<Vec<_>>()
}) }),
.transpose()?, named: dataset.available_named_graphs().map(|graphs| {
named: dataset
.available_named_graphs()
.map(|graphs| {
graphs graphs
.iter() .iter()
.flat_map(|g| { .map(|g| get_encoded_named_or_blank_node(g.as_ref()))
storage .collect::<Vec<_>>()
.get_encoded_named_or_blank_node(g.as_ref()) }),
.transpose()
})
.collect::<Result<Vec<_>, _>>()
})
.transpose()?,
}; };
Ok(Self { Ok(Self {
storage, storage,

@ -10,7 +10,7 @@ use crate::sparql::plan_builder::PlanBuilder;
use crate::sparql::{EvaluationError, UpdateOptions}; use crate::sparql::{EvaluationError, UpdateOptions};
use crate::storage::io::load_graph; use crate::storage::io::load_graph;
use crate::storage::numeric_encoder::{ use crate::storage::numeric_encoder::{
EncodedQuad, EncodedTerm, ReadEncoder, StrLookup, WriteEncoder, get_encoded_literal, get_encoded_named_node, EncodedQuad, EncodedTerm, StrLookup, WriteEncoder,
}; };
use crate::storage::Storage; use crate::storage::Storage;
use http::header::{ACCEPT, CONTENT_TYPE, USER_AGENT}; use http::header::{ACCEPT, CONTENT_TYPE, USER_AGENT};
@ -101,10 +101,9 @@ impl<'a> SimpleUpdateEvaluator<'a> {
fn eval_delete_data(&mut self, data: &[Quad]) -> Result<(), EvaluationError> { fn eval_delete_data(&mut self, data: &[Quad]) -> Result<(), EvaluationError> {
for quad in data { for quad in data {
if let Some(quad) = self.encode_quad_for_deletion(quad)? { let quad = self.encode_quad_for_deletion(quad)?;
self.storage.remove(&quad)?; self.storage.remove(&quad)?;
} }
}
Ok(()) Ok(())
} }
@ -238,12 +237,10 @@ impl<'a> SimpleUpdateEvaluator<'a> {
fn eval_clear(&mut self, graph: &GraphTarget, silent: bool) -> Result<(), EvaluationError> { fn eval_clear(&mut self, graph: &GraphTarget, silent: bool) -> Result<(), EvaluationError> {
match graph { match graph {
GraphTarget::NamedNode(graph_name) => { GraphTarget::NamedNode(graph_name) => {
if let Some(graph_name) = self.encode_named_node_for_deletion(graph_name)? { let graph_name = self.encode_named_node_for_deletion(graph_name);
if self.storage.contains_named_graph(graph_name)? { if self.storage.contains_named_graph(graph_name)? {
return Ok(self.storage.clear_graph(graph_name)?); Ok(self.storage.clear_graph(graph_name)?)
} } else if silent {
}
if silent {
Ok(()) Ok(())
} else { } else {
Err(EvaluationError::msg(format!( Err(EvaluationError::msg(format!(
@ -273,13 +270,11 @@ impl<'a> SimpleUpdateEvaluator<'a> {
fn eval_drop(&mut self, graph: &GraphTarget, silent: bool) -> Result<(), EvaluationError> { fn eval_drop(&mut self, graph: &GraphTarget, silent: bool) -> Result<(), EvaluationError> {
match graph { match graph {
GraphTarget::NamedNode(graph_name) => { GraphTarget::NamedNode(graph_name) => {
if let Some(graph_name) = self.encode_named_node_for_deletion(graph_name)? { let graph_name = self.encode_named_node_for_deletion(graph_name);
if self.storage.contains_named_graph(graph_name)? { if self.storage.contains_named_graph(graph_name)? {
self.storage.remove_named_graph(graph_name)?; self.storage.remove_named_graph(graph_name)?;
return Ok(()); Ok(())
} } else if silent {
}
if silent {
Ok(()) Ok(())
} else { } else {
Err(EvaluationError::msg(format!( Err(EvaluationError::msg(format!(
@ -470,56 +465,33 @@ impl<'a> SimpleUpdateEvaluator<'a> {
})?) })?)
} }
fn encode_quad_for_deletion( fn encode_quad_for_deletion(&mut self, quad: &Quad) -> Result<EncodedQuad, EvaluationError> {
&mut self, Ok(EncodedQuad {
quad: &Quad, subject: match &quad.subject {
) -> Result<Option<EncodedQuad>, EvaluationError> {
Ok(Some(EncodedQuad {
subject: if let Some(subject) = match &quad.subject {
NamedOrBlankNode::NamedNode(subject) => { NamedOrBlankNode::NamedNode(subject) => {
self.encode_named_node_for_deletion(subject)? self.encode_named_node_for_deletion(subject)
} }
NamedOrBlankNode::BlankNode(_) => { NamedOrBlankNode::BlankNode(_) => {
return Err(EvaluationError::msg( return Err(EvaluationError::msg(
"Blank nodes are not allowed in DELETE DATA", "Blank nodes are not allowed in DELETE DATA",
)) ))
} }
} {
subject
} else {
return Ok(None);
},
predicate: if let Some(predicate) =
self.encode_named_node_for_deletion(&quad.predicate)?
{
predicate
} else {
return Ok(None);
}, },
object: if let Some(object) = match &quad.object { predicate: self.encode_named_node_for_deletion(&quad.predicate),
Term::NamedNode(object) => self.encode_named_node_for_deletion(object)?, object: match &quad.object {
Term::NamedNode(object) => self.encode_named_node_for_deletion(object),
Term::BlankNode(_) => { Term::BlankNode(_) => {
return Err(EvaluationError::msg( return Err(EvaluationError::msg(
"Blank nodes are not allowed in DELETE DATA", "Blank nodes are not allowed in DELETE DATA",
)) ))
} }
Term::Literal(object) => self.encode_literal_for_deletion(object)?, Term::Literal(object) => self.encode_literal_for_deletion(object),
} {
object
} else {
return Ok(None);
}, },
graph_name: if let Some(graph_name) = match &quad.graph_name { graph_name: match &quad.graph_name {
GraphName::NamedNode(graph_name) => { GraphName::NamedNode(graph_name) => self.encode_named_node_for_deletion(graph_name),
self.encode_named_node_for_deletion(graph_name)? GraphName::DefaultGraph => EncodedTerm::DefaultGraph,
}
GraphName::DefaultGraph => Some(EncodedTerm::DefaultGraph),
} {
graph_name
} else {
return Ok(None);
}, },
})) })
} }
fn encode_quad_pattern_for_deletion( fn encode_quad_pattern_for_deletion(
@ -537,7 +509,7 @@ impl<'a> SimpleUpdateEvaluator<'a> {
return Ok(None); return Ok(None);
}, },
predicate: if let Some(predicate) = predicate: if let Some(predicate) =
self.encode_named_node_or_var_for_deletion(&quad.predicate, variables, values)? self.encode_named_node_or_var_for_deletion(&quad.predicate, variables, values)
{ {
predicate predicate
} else { } else {
@ -552,7 +524,7 @@ impl<'a> SimpleUpdateEvaluator<'a> {
}, },
graph_name: if let Some(graph_name) = &quad.graph_name { graph_name: if let Some(graph_name) = &quad.graph_name {
if let Some(graph_name) = if let Some(graph_name) =
self.encode_named_node_or_var_for_deletion(graph_name, variables, values)? self.encode_named_node_or_var_for_deletion(graph_name, variables, values)
{ {
graph_name graph_name
} else { } else {
@ -570,15 +542,17 @@ impl<'a> SimpleUpdateEvaluator<'a> {
variables: &[Variable], variables: &[Variable],
values: &[Option<EncodedTerm>], values: &[Option<EncodedTerm>],
) -> Result<Option<EncodedTerm>, EvaluationError> { ) -> Result<Option<EncodedTerm>, EvaluationError> {
match term { Ok(match term {
TermOrVariable::Term(term) => match term { TermOrVariable::Term(term) => match term {
Term::NamedNode(term) => self.encode_named_node_for_deletion(term), Term::NamedNode(term) => Some(self.encode_named_node_for_deletion(term)),
Term::BlankNode(_) => Err(EvaluationError::msg( Term::BlankNode(_) => {
return Err(EvaluationError::msg(
"Blank nodes are not allowed in DELETE patterns", "Blank nodes are not allowed in DELETE patterns",
)), ))
Term::Literal(term) => self.encode_literal_for_deletion(term), }
Term::Literal(term) => Some(self.encode_literal_for_deletion(term)),
}, },
TermOrVariable::Variable(v) => Ok( TermOrVariable::Variable(v) => {
if let Some(Some(term)) = variables if let Some(Some(term)) = variables
.iter() .iter()
.position(|v2| v == v2) .position(|v2| v == v2)
@ -587,19 +561,19 @@ impl<'a> SimpleUpdateEvaluator<'a> {
Some(*term) Some(*term)
} else { } else {
None None
},
),
} }
} }
})
}
fn encode_named_node_or_var_for_deletion( fn encode_named_node_or_var_for_deletion(
&self, &self,
term: &NamedNodeOrVariable, term: &NamedNodeOrVariable,
variables: &[Variable], variables: &[Variable],
values: &[Option<EncodedTerm>], values: &[Option<EncodedTerm>],
) -> Result<Option<EncodedTerm>, EvaluationError> { ) -> Option<EncodedTerm> {
Ok(match term { match term {
NamedNodeOrVariable::NamedNode(term) => self.encode_named_node_for_deletion(term)?, NamedNodeOrVariable::NamedNode(term) => Some(self.encode_named_node_for_deletion(term)),
NamedNodeOrVariable::Variable(v) => { NamedNodeOrVariable::Variable(v) => {
if let Some(Some(term)) = variables if let Some(Some(term)) = variables
.iter() .iter()
@ -615,23 +589,15 @@ impl<'a> SimpleUpdateEvaluator<'a> {
None None
} }
} }
}) }
} }
fn encode_named_node_for_deletion( fn encode_named_node_for_deletion(&self, term: &NamedNode) -> EncodedTerm {
&self, get_encoded_named_node(NamedNodeRef::new_unchecked(&term.iri))
term: &NamedNode,
) -> Result<Option<EncodedTerm>, EvaluationError> {
Ok(self
.storage
.get_encoded_named_node(NamedNodeRef::new_unchecked(&term.iri))?)
} }
fn encode_literal_for_deletion( fn encode_literal_for_deletion(&self, term: &Literal) -> EncodedTerm {
&self, get_encoded_literal(match term {
term: &Literal,
) -> Result<Option<EncodedTerm>, EvaluationError> {
Ok(self.storage.get_encoded_literal(match term {
Literal::Simple { value } => LiteralRef::new_simple_literal(value), Literal::Simple { value } => LiteralRef::new_simple_literal(value),
Literal::LanguageTaggedString { value, language } => { Literal::LanguageTaggedString { value, language } => {
LiteralRef::new_language_tagged_literal_unchecked(value, language) LiteralRef::new_language_tagged_literal_unchecked(value, language)
@ -639,6 +605,6 @@ impl<'a> SimpleUpdateEvaluator<'a> {
Literal::Typed { value, datatype } => { Literal::Typed { value, datatype } => {
LiteralRef::new_typed_literal(value, NamedNodeRef::new_unchecked(&datatype.iri)) LiteralRef::new_typed_literal(value, NamedNodeRef::new_unchecked(&datatype.iri))
} }
})?) })
} }
} }

@ -718,10 +718,7 @@ mod tests {
]; ];
for term in terms { for term in terms {
let encoded = store.encode_term(term.as_ref()).unwrap(); let encoded = store.encode_term(term.as_ref()).unwrap();
assert_eq!( assert_eq!(encoded, get_encoded_term(term.as_ref()));
Some(encoded),
store.get_encoded_term(term.as_ref()).unwrap()
);
assert_eq!(term, store.decode_term(encoded).unwrap()); assert_eq!(term, store.decode_term(encoded).unwrap());
let mut buffer = Vec::new(); let mut buffer = Vec::new();

@ -497,27 +497,14 @@ pub(crate) trait StrLookup {
pub(crate) trait StrContainer: StrLookup { pub(crate) trait StrContainer: StrLookup {
fn insert_str(&self, key: StrHash, value: &str) -> Result<bool, Self::Error>; fn insert_str(&self, key: StrHash, value: &str) -> Result<bool, Self::Error>;
} }
pub(crate) fn get_encoded_named_node(named_node: NamedNodeRef<'_>) -> EncodedTerm {
/// Tries to encode a term based on the existing strings (does not insert anything) EncodedTerm::NamedNode {
pub(crate) trait ReadEncoder: StrLookup { iri_id: StrHash::new(named_node.as_str()),
fn get_encoded_named_node(
&self,
named_node: NamedNodeRef<'_>,
) -> Result<Option<EncodedTerm>, Self::Error> {
Ok(Some(EncodedTerm::NamedNode {
iri_id: if let Some(iri_id) = self.get_encoded_str(named_node.as_str())? {
iri_id
} else {
return Ok(None);
},
}))
} }
}
fn get_encoded_blank_node( pub(crate) fn get_encoded_blank_node(blank_node: BlankNodeRef<'_>) -> EncodedTerm {
&self, if let Some(id) = blank_node.id() {
blank_node: BlankNodeRef<'_>,
) -> Result<Option<EncodedTerm>, Self::Error> {
Ok(Some(if let Some(id) = blank_node.id() {
EncodedTerm::NumericalBlankNode { id } EncodedTerm::NumericalBlankNode { id }
} else { } else {
let id = blank_node.as_str(); let id = blank_node.as_str();
@ -525,66 +512,38 @@ pub(crate) trait ReadEncoder: StrLookup {
EncodedTerm::SmallBlankNode(id) EncodedTerm::SmallBlankNode(id)
} else { } else {
EncodedTerm::BigBlankNode { EncodedTerm::BigBlankNode {
id_id: if let Some(id_id) = self.get_encoded_str(id)? { id_id: StrHash::new(id),
id_id
} else {
return Ok(None);
},
} }
} }
}))
} }
}
fn get_encoded_literal( pub(crate) fn get_encoded_literal(literal: LiteralRef<'_>) -> EncodedTerm {
&self,
literal: LiteralRef<'_>,
) -> Result<Option<EncodedTerm>, Self::Error> {
let value = literal.value(); let value = literal.value();
let datatype = literal.datatype().as_str(); let datatype = literal.datatype().as_str();
Ok(Some( let native_encoding = match datatype {
match match datatype {
"http://www.w3.org/1999/02/22-rdf-syntax-ns#langString" => { "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString" => {
if let Some(language) = literal.language() { if let Some(language) = literal.language() {
if let Ok(value) = SmallString::try_from(value) { Some(if let Ok(value) = SmallString::try_from(value) {
if let Ok(language) = SmallString::try_from(language) { if let Ok(language) = SmallString::try_from(language) {
Some(EncodedTerm::SmallSmallLangStringLiteral { value, language }) EncodedTerm::SmallSmallLangStringLiteral { value, language }
} else { } else {
Some(EncodedTerm::SmallBigLangStringLiteral { EncodedTerm::SmallBigLangStringLiteral {
value, value,
language_id: if let Some(language_id) = language_id: StrHash::new(language),
self.get_encoded_str(language)? }
{
language_id
} else {
return Ok(None);
},
})
} }
} else if let Ok(language) = SmallString::try_from(language) { } else if let Ok(language) = SmallString::try_from(language) {
Some(EncodedTerm::BigSmallLangStringLiteral { EncodedTerm::BigSmallLangStringLiteral {
value_id: if let Some(value_id) = self.get_encoded_str(value)? { value_id: StrHash::new(value),
value_id
} else {
return Ok(None);
},
language, language,
}) }
} else {
Some(EncodedTerm::BigBigLangStringLiteral {
value_id: if let Some(value_id) = self.get_encoded_str(value)? {
value_id
} else {
return Ok(None);
},
language_id: if let Some(language_id) =
self.get_encoded_str(language)?
{
language_id
} else { } else {
return Ok(None); EncodedTerm::BigBigLangStringLiteral {
}, value_id: StrHash::new(value),
}) language_id: StrHash::new(language),
} }
})
} else { } else {
None None
} }
@ -596,11 +555,7 @@ pub(crate) trait ReadEncoder: StrLookup {
EncodedTerm::SmallStringLiteral(value) EncodedTerm::SmallStringLiteral(value)
} else { } else {
EncodedTerm::BigStringLiteral { EncodedTerm::BigStringLiteral {
value_id: if let Some(value_id) = self.get_encoded_str(value)? { value_id: StrHash::new(value),
value_id
} else {
return Ok(None);
},
} }
}) })
} }
@ -633,110 +588,56 @@ pub(crate) trait ReadEncoder: StrLookup {
"http://www.w3.org/2001/XMLSchema#yearMonthDuration" => { "http://www.w3.org/2001/XMLSchema#yearMonthDuration" => {
parse_year_month_duration_str(value) parse_year_month_duration_str(value)
} }
"http://www.w3.org/2001/XMLSchema#dayTimeDuration" => { "http://www.w3.org/2001/XMLSchema#dayTimeDuration" => parse_day_time_duration_str(value),
parse_day_time_duration_str(value)
}
_ => None, _ => None,
} { };
match native_encoding {
Some(term) => term, Some(term) => term,
None => { None => {
if let Ok(value) = SmallString::try_from(value) { if let Ok(value) = SmallString::try_from(value) {
EncodedTerm::SmallTypedLiteral { EncodedTerm::SmallTypedLiteral {
value, value,
datatype_id: if let Some(datatype_id) = datatype_id: StrHash::new(datatype),
self.get_encoded_str(datatype)?
{
datatype_id
} else {
return Ok(None);
},
} }
} else { } else {
EncodedTerm::BigTypedLiteral { EncodedTerm::BigTypedLiteral {
value_id: if let Some(value_id) = self.get_encoded_str(value)? { value_id: StrHash::new(value),
value_id datatype_id: StrHash::new(datatype),
} else {
return Ok(None);
},
datatype_id: if let Some(datatype_id) =
self.get_encoded_str(datatype)?
{
datatype_id
} else {
return Ok(None);
},
} }
} }
} }
},
))
} }
}
fn get_encoded_named_or_blank_node( pub(crate) fn get_encoded_named_or_blank_node(term: NamedOrBlankNodeRef<'_>) -> EncodedTerm {
&self,
term: NamedOrBlankNodeRef<'_>,
) -> Result<Option<EncodedTerm>, Self::Error> {
match term { match term {
NamedOrBlankNodeRef::NamedNode(named_node) => self.get_encoded_named_node(named_node), NamedOrBlankNodeRef::NamedNode(named_node) => get_encoded_named_node(named_node),
NamedOrBlankNodeRef::BlankNode(blank_node) => self.get_encoded_blank_node(blank_node), NamedOrBlankNodeRef::BlankNode(blank_node) => get_encoded_blank_node(blank_node),
}
} }
}
fn get_encoded_term(&self, term: TermRef<'_>) -> Result<Option<EncodedTerm>, Self::Error> { pub(crate) fn get_encoded_term(term: TermRef<'_>) -> EncodedTerm {
match term { match term {
TermRef::NamedNode(named_node) => self.get_encoded_named_node(named_node), TermRef::NamedNode(named_node) => get_encoded_named_node(named_node),
TermRef::BlankNode(blank_node) => self.get_encoded_blank_node(blank_node), TermRef::BlankNode(blank_node) => get_encoded_blank_node(blank_node),
TermRef::Literal(literal) => self.get_encoded_literal(literal), TermRef::Literal(literal) => get_encoded_literal(literal),
}
} }
}
fn get_encoded_graph_name( pub(crate) fn get_encoded_graph_name(name: GraphNameRef<'_>) -> EncodedTerm {
&self,
name: GraphNameRef<'_>,
) -> Result<Option<EncodedTerm>, Self::Error> {
match name { match name {
GraphNameRef::NamedNode(named_node) => self.get_encoded_named_node(named_node), GraphNameRef::NamedNode(named_node) => get_encoded_named_node(named_node),
GraphNameRef::BlankNode(blank_node) => self.get_encoded_blank_node(blank_node), GraphNameRef::BlankNode(blank_node) => get_encoded_blank_node(blank_node),
GraphNameRef::DefaultGraph => Ok(Some(EncodedTerm::DefaultGraph)), GraphNameRef::DefaultGraph => EncodedTerm::DefaultGraph,
}
} }
fn get_encoded_quad(&self, quad: QuadRef<'_>) -> Result<Option<EncodedQuad>, Self::Error> {
Ok(Some(EncodedQuad {
subject: if let Some(subject) = self.get_encoded_named_or_blank_node(quad.subject)? {
subject
} else {
return Ok(None);
},
predicate: if let Some(predicate) = self.get_encoded_named_node(quad.predicate)? {
predicate
} else {
return Ok(None);
},
object: if let Some(object) = self.get_encoded_term(quad.object)? {
object
} else {
return Ok(None);
},
graph_name: if let Some(graph_name) = self.get_encoded_graph_name(quad.graph_name)? {
graph_name
} else {
return Ok(None);
},
}))
}
fn get_encoded_str(&self, value: &str) -> Result<Option<StrHash>, Self::Error>;
} }
impl<S: StrLookup> ReadEncoder for S { pub(crate) fn get_encoded_quad(quad: QuadRef<'_>) -> EncodedQuad {
fn get_encoded_str(&self, value: &str) -> Result<Option<StrHash>, Self::Error> { EncodedQuad {
let key = StrHash::new(value); subject: get_encoded_named_or_blank_node(quad.subject),
Ok(if self.contains_str(key)? { predicate: get_encoded_named_node(quad.predicate),
Some(key) object: get_encoded_term(quad.object),
} else { graph_name: get_encoded_graph_name(quad.graph_name),
None
})
} }
} }

@ -29,12 +29,6 @@
//! # Result::<_,Box<dyn std::error::Error>>::Ok(()) //! # Result::<_,Box<dyn std::error::Error>>::Ok(())
//! ``` //! ```
use std::convert::TryInto;
use std::io::{BufRead, Write};
use std::iter::{once, Once};
use std::path::Path;
use std::{fmt, io, str};
use crate::io::{DatasetFormat, GraphFormat}; use crate::io::{DatasetFormat, GraphFormat};
use crate::model::*; use crate::model::*;
use crate::sparql::{ use crate::sparql::{
@ -42,13 +36,20 @@ use crate::sparql::{
UpdateOptions, UpdateOptions,
}; };
use crate::storage::io::{dump_dataset, dump_graph, load_dataset, load_graph}; use crate::storage::io::{dump_dataset, dump_graph, load_dataset, load_graph};
use crate::storage::numeric_encoder::{Decoder, EncodedTerm, ReadEncoder, WriteEncoder}; use crate::storage::numeric_encoder::{
get_encoded_graph_name, get_encoded_named_node, get_encoded_named_or_blank_node,
get_encoded_quad, get_encoded_term, Decoder, WriteEncoder,
};
pub use crate::storage::ConflictableTransactionError; pub use crate::storage::ConflictableTransactionError;
pub use crate::storage::TransactionError; pub use crate::storage::TransactionError;
pub use crate::storage::UnabortableTransactionError; pub use crate::storage::UnabortableTransactionError;
use crate::storage::{ use crate::storage::{
ChainedDecodingQuadIterator, DecodingGraphIterator, Storage, StorageTransaction, ChainedDecodingQuadIterator, DecodingGraphIterator, Storage, StorageTransaction,
}; };
use std::convert::TryInto;
use std::io::{BufRead, Write};
use std::path::Path;
use std::{fmt, io, str};
/// An on-on disk [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset). /// An on-on disk [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset).
/// Allows to query and update it using SPARQL. /// Allows to query and update it using SPARQL.
@ -169,72 +170,14 @@ impl Store {
graph_name: Option<GraphNameRef<'_>>, graph_name: Option<GraphNameRef<'_>>,
) -> QuadIter { ) -> QuadIter {
QuadIter { QuadIter {
inner: match self.get_encoded_quad_pattern(subject, predicate, object, graph_name) { iter: self.storage.quads_for_pattern(
Ok(Some((subject, predicate, object, graph_name))) => QuadIterInner::Quads { subject.map(|s| get_encoded_named_or_blank_node(s)),
iter: self predicate.map(|p| get_encoded_named_node(p)),
.storage object.map(|o| get_encoded_term(o)),
.quads_for_pattern(subject, predicate, object, graph_name), graph_name.map(|g| get_encoded_graph_name(g)),
store: self.clone(), ),
}, storage: self.storage.clone(),
Ok(None) => QuadIterInner::Empty,
Err(error) => QuadIterInner::Error(once(error)),
},
}
} }
fn get_encoded_quad_pattern(
&self,
subject: Option<NamedOrBlankNodeRef<'_>>,
predicate: Option<NamedNodeRef<'_>>,
object: Option<TermRef<'_>>,
graph_name: Option<GraphNameRef<'_>>,
) -> Result<
Option<(
Option<EncodedTerm>,
Option<EncodedTerm>,
Option<EncodedTerm>,
Option<EncodedTerm>,
)>,
io::Error,
> {
Ok(Some((
if let Some(subject) = transpose(
subject
.map(|t| self.storage.get_encoded_named_or_blank_node(t))
.transpose()?,
) {
subject
} else {
return Ok(None);
},
if let Some(predicate) = transpose(
predicate
.map(|t| self.storage.get_encoded_named_node(t))
.transpose()?,
) {
predicate
} else {
return Ok(None);
},
if let Some(object) = transpose(
object
.map(|t| self.storage.get_encoded_term(t))
.transpose()?,
) {
object
} else {
return Ok(None);
},
if let Some(graph_name) = transpose(
graph_name
.map(|t| self.storage.get_encoded_graph_name(t))
.transpose()?,
) {
graph_name
} else {
return Ok(None);
},
)))
} }
/// Returns all the quads contained in the store /// Returns all the quads contained in the store
@ -244,11 +187,8 @@ impl Store {
/// 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.storage.get_encoded_quad(quad.into())? { let quad = get_encoded_quad(quad.into());
self.storage.contains(&quad) self.storage.contains(&quad)
} else {
Ok(false)
}
} }
/// Returns the number of quads in the store /// Returns the number of quads in the store
@ -440,11 +380,8 @@ impl Store {
/// 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](Store::transaction()) if you do not want that. /// Use a (memory greedy) [transaction](Store::transaction()) if you do not want that.
pub fn remove<'a>(&self, quad: impl Into<QuadRef<'a>>) -> Result<bool, io::Error> { pub fn remove<'a>(&self, quad: impl Into<QuadRef<'a>>) -> Result<bool, io::Error> {
if let Some(quad) = self.storage.get_encoded_quad(quad.into())? { let quad = get_encoded_quad(quad.into());
self.storage.remove(&quad) self.storage.remove(&quad)
} else {
Ok(false)
}
} }
/// Dumps a store graph into a file. /// Dumps a store graph into a file.
@ -537,14 +474,8 @@ impl Store {
&self, &self,
graph_name: impl Into<NamedOrBlankNodeRef<'a>>, graph_name: impl Into<NamedOrBlankNodeRef<'a>>,
) -> Result<bool, io::Error> { ) -> Result<bool, io::Error> {
if let Some(graph_name) = self let graph_name = get_encoded_named_or_blank_node(graph_name.into());
.storage
.get_encoded_named_or_blank_node(graph_name.into())?
{
self.storage.contains_named_graph(graph_name) self.storage.contains_named_graph(graph_name)
} else {
Ok(false)
}
} }
/// Inserts a graph into this store /// Inserts a graph into this store
@ -592,11 +523,8 @@ impl Store {
&self, &self,
graph_name: impl Into<GraphNameRef<'a>>, graph_name: impl Into<GraphNameRef<'a>>,
) -> Result<(), io::Error> { ) -> Result<(), io::Error> {
if let Some(graph_name) = self.storage.get_encoded_graph_name(graph_name.into())? { let graph_name = get_encoded_graph_name(graph_name.into());
self.storage.clear_graph(graph_name) self.storage.clear_graph(graph_name)
} else {
Ok(())
}
} }
/// Removes a graph from this store. /// Removes a graph from this store.
@ -623,14 +551,8 @@ impl Store {
&self, &self,
graph_name: impl Into<NamedOrBlankNodeRef<'a>>, graph_name: impl Into<NamedOrBlankNodeRef<'a>>,
) -> Result<bool, io::Error> { ) -> Result<bool, io::Error> {
if let Some(graph_name) = self let graph_name = get_encoded_named_or_blank_node(graph_name.into());
.storage
.get_encoded_named_or_blank_node(graph_name.into())?
{
self.storage.remove_named_graph(graph_name) self.storage.remove_named_graph(graph_name)
} else {
Ok(false)
}
} }
/// Clears the store. /// Clears the store.
@ -733,7 +655,6 @@ impl Transaction<'_> {
/// use oxigraph::store::{Store, ConflictableTransactionError}; /// use oxigraph::store::{Store, ConflictableTransactionError};
/// use oxigraph::io::DatasetFormat; /// use oxigraph::io::DatasetFormat;
/// use oxigraph::model::*; /// use oxigraph::model::*;
/// use oxigraph::store::ConflictableTransactionError;
/// ///
/// let store = Store::new()?; /// let store = Store::new()?;
/// ///
@ -784,11 +705,8 @@ impl Transaction<'_> {
&self, &self,
quad: impl Into<QuadRef<'a>>, quad: impl Into<QuadRef<'a>>,
) -> Result<bool, UnabortableTransactionError> { ) -> Result<bool, UnabortableTransactionError> {
if let Some(quad) = self.storage.get_encoded_quad(quad.into())? { let quad = get_encoded_quad(quad.into());
self.storage.remove(&quad) self.storage.remove(&quad)
} else {
Ok(false)
}
} }
/// Inserts a graph into this store during the transaction /// Inserts a graph into this store during the transaction
@ -805,30 +723,18 @@ impl Transaction<'_> {
/// An iterator returning the quads contained in a [`Store`]. /// An iterator returning the quads contained in a [`Store`].
pub struct QuadIter { pub struct QuadIter {
inner: QuadIterInner,
}
enum QuadIterInner {
Quads {
iter: ChainedDecodingQuadIterator, iter: ChainedDecodingQuadIterator,
store: Store, storage: Storage,
},
Error(Once<io::Error>),
Empty,
} }
impl Iterator for QuadIter { impl Iterator for QuadIter {
type Item = Result<Quad, io::Error>; type Item = Result<Quad, io::Error>;
fn next(&mut self) -> Option<Result<Quad, io::Error>> { fn next(&mut self) -> Option<Result<Quad, io::Error>> {
match &mut self.inner { Some(match self.iter.next()? {
QuadIterInner::Quads { iter, store } => Some(match iter.next()? { Ok(quad) => self.storage.decode_quad(&quad).map_err(|e| e.into()),
Ok(quad) => store.storage.decode_quad(&quad).map_err(|e| e.into()),
Err(error) => Err(error), Err(error) => Err(error),
}), })
QuadIterInner::Error(iter) => iter.next().map(Err),
QuadIterInner::Empty => None,
}
} }
} }
@ -854,14 +760,6 @@ impl Iterator for GraphNameIter {
} }
} }
fn transpose<T>(o: Option<Option<T>>) -> Option<Option<T>> {
match o {
Some(Some(v)) => Some(Some(v)),
Some(None) => None,
None => Some(None),
}
}
#[test] #[test]
fn store() -> Result<(), io::Error> { fn store() -> Result<(), io::Error> {
use crate::model::*; use crate::model::*;

Loading…
Cancel
Save