Makes term encoding not fail if the string is not stored

pull/171/head
Tpt 4 years ago
parent 68aab2563c
commit aa7a23b94d
  1. 37
      lib/src/sparql/dataset.rs
  2. 128
      lib/src/sparql/update.rs
  3. 5
      lib/src/storage/binary_encoder.rs
  4. 339
      lib/src/storage/numeric_encoder.rs
  5. 168
      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() graphs
.map(|graphs| { .iter()
graphs .map(|g| get_encoded_graph_name(g.as_ref()))
.iter() .collect::<Vec<_>>()
.flat_map(|g| storage.get_encoded_graph_name(g.as_ref()).transpose()) }),
.collect::<Result<Vec<_>, _>>() named: dataset.available_named_graphs().map(|graphs| {
}) graphs
.transpose()?, .iter()
named: dataset .map(|g| get_encoded_named_or_blank_node(g.as_ref()))
.available_named_graphs() .collect::<Vec<_>>()
.map(|graphs| { }),
graphs
.iter()
.flat_map(|g| {
storage
.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,9 +101,8 @@ 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) = predicate: self.encode_named_node_for_deletion(&quad.predicate),
self.encode_named_node_for_deletion(&quad.predicate)? object: match &quad.object {
{ Term::NamedNode(object) => self.encode_named_node_for_deletion(object),
predicate
} else {
return Ok(None);
},
object: if let Some(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(_) => {
"Blank nodes are not allowed in DELETE patterns", return Err(EvaluationError::msg(
)), "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,9 +561,9 @@ 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(
@ -597,9 +571,9 @@ impl<'a> SimpleUpdateEvaluator<'a> {
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,246 +497,147 @@ 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<'_>, EncodedTerm::NumericalBlankNode { id }
) -> Result<Option<EncodedTerm>, Self::Error> { } else {
Ok(Some(if let Some(id) = blank_node.id() { let id = blank_node.as_str();
EncodedTerm::NumericalBlankNode { id } if let Ok(id) = id.try_into() {
EncodedTerm::SmallBlankNode(id)
} else { } else {
let id = blank_node.as_str(); EncodedTerm::BigBlankNode {
if let Ok(id) = id.try_into() { id_id: StrHash::new(id),
EncodedTerm::SmallBlankNode(id)
} else {
EncodedTerm::BigBlankNode {
id_id: if let Some(id_id) = self.get_encoded_str(id)? {
id_id
} else {
return Ok(None);
},
}
} }
})) }
} }
}
fn get_encoded_literal( pub(crate) fn get_encoded_literal(literal: LiteralRef<'_>) -> EncodedTerm {
&self, let value = literal.value();
literal: LiteralRef<'_>, let datatype = literal.datatype().as_str();
) -> Result<Option<EncodedTerm>, Self::Error> { let native_encoding = match datatype {
let value = literal.value(); "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString" => {
let datatype = literal.datatype().as_str(); if let Some(language) = literal.language() {
Ok(Some( Some(if let Ok(value) = SmallString::try_from(value) {
match match datatype { if let Ok(language) = SmallString::try_from(language) {
"http://www.w3.org/1999/02/22-rdf-syntax-ns#langString" => { EncodedTerm::SmallSmallLangStringLiteral { value, language }
if let Some(language) = literal.language() {
if let Ok(value) = SmallString::try_from(value) {
if let Ok(language) = SmallString::try_from(language) {
Some(EncodedTerm::SmallSmallLangStringLiteral { value, language })
} else {
Some(EncodedTerm::SmallBigLangStringLiteral {
value,
language_id: if let Some(language_id) =
self.get_encoded_str(language)?
{
language_id
} else {
return Ok(None);
},
})
}
} else if let Ok(language) = SmallString::try_from(language) {
Some(EncodedTerm::BigSmallLangStringLiteral {
value_id: if let Some(value_id) = self.get_encoded_str(value)? {
value_id
} else {
return Ok(None);
},
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 {
return Ok(None);
},
})
}
} else {
None
}
}
"http://www.w3.org/2001/XMLSchema#boolean" => parse_boolean_str(value),
"http://www.w3.org/2001/XMLSchema#string" => {
let value = value;
Some(if let Ok(value) = SmallString::try_from(value) {
EncodedTerm::SmallStringLiteral(value)
} else { } else {
EncodedTerm::BigStringLiteral { EncodedTerm::SmallBigLangStringLiteral {
value_id: if let Some(value_id) = self.get_encoded_str(value)? {
value_id
} else {
return Ok(None);
},
}
})
}
"http://www.w3.org/2001/XMLSchema#float" => parse_float_str(value),
"http://www.w3.org/2001/XMLSchema#double" => parse_double_str(value),
"http://www.w3.org/2001/XMLSchema#integer"
| "http://www.w3.org/2001/XMLSchema#byte"
| "http://www.w3.org/2001/XMLSchema#short"
| "http://www.w3.org/2001/XMLSchema#int"
| "http://www.w3.org/2001/XMLSchema#long"
| "http://www.w3.org/2001/XMLSchema#unsignedByte"
| "http://www.w3.org/2001/XMLSchema#unsignedShort"
| "http://www.w3.org/2001/XMLSchema#unsignedInt"
| "http://www.w3.org/2001/XMLSchema#unsignedLong"
| "http://www.w3.org/2001/XMLSchema#positiveInteger"
| "http://www.w3.org/2001/XMLSchema#negativeInteger"
| "http://www.w3.org/2001/XMLSchema#nonPositiveInteger"
| "http://www.w3.org/2001/XMLSchema#nonNegativeInteger" => parse_integer_str(value),
"http://www.w3.org/2001/XMLSchema#decimal" => parse_decimal_str(value),
"http://www.w3.org/2001/XMLSchema#dateTime"
| "http://www.w3.org/2001/XMLSchema#dateTimeStamp" => parse_date_time_str(value),
"http://www.w3.org/2001/XMLSchema#time" => parse_time_str(value),
"http://www.w3.org/2001/XMLSchema#date" => parse_date_str(value),
"http://www.w3.org/2001/XMLSchema#gYearMonth" => parse_g_year_month_str(value),
"http://www.w3.org/2001/XMLSchema#gYear" => parse_g_year_str(value),
"http://www.w3.org/2001/XMLSchema#gMonthDay" => parse_g_month_day_str(value),
"http://www.w3.org/2001/XMLSchema#gDay" => parse_g_day_str(value),
"http://www.w3.org/2001/XMLSchema#gMonth" => parse_g_month_str(value),
"http://www.w3.org/2001/XMLSchema#duration" => parse_duration_str(value),
"http://www.w3.org/2001/XMLSchema#yearMonthDuration" => {
parse_year_month_duration_str(value)
}
"http://www.w3.org/2001/XMLSchema#dayTimeDuration" => {
parse_day_time_duration_str(value)
}
_ => None,
} {
Some(term) => term,
None => {
if let Ok(value) = SmallString::try_from(value) {
EncodedTerm::SmallTypedLiteral {
value, value,
datatype_id: if let Some(datatype_id) = language_id: StrHash::new(language),
self.get_encoded_str(datatype)?
{
datatype_id
} else {
return Ok(None);
},
}
} else {
EncodedTerm::BigTypedLiteral {
value_id: if let Some(value_id) = self.get_encoded_str(value)? {
value_id
} else {
return Ok(None);
},
datatype_id: if let Some(datatype_id) =
self.get_encoded_str(datatype)?
{
datatype_id
} else {
return Ok(None);
},
} }
} }
} else if let Ok(language) = SmallString::try_from(language) {
EncodedTerm::BigSmallLangStringLiteral {
value_id: StrHash::new(value),
language,
}
} else {
EncodedTerm::BigBigLangStringLiteral {
value_id: StrHash::new(value),
language_id: StrHash::new(language),
}
})
} else {
None
}
}
"http://www.w3.org/2001/XMLSchema#boolean" => parse_boolean_str(value),
"http://www.w3.org/2001/XMLSchema#string" => {
let value = value;
Some(if let Ok(value) = SmallString::try_from(value) {
EncodedTerm::SmallStringLiteral(value)
} else {
EncodedTerm::BigStringLiteral {
value_id: StrHash::new(value),
} }
}, })
))
}
fn get_encoded_named_or_blank_node(
&self,
term: NamedOrBlankNodeRef<'_>,
) -> Result<Option<EncodedTerm>, Self::Error> {
match term {
NamedOrBlankNodeRef::NamedNode(named_node) => self.get_encoded_named_node(named_node),
NamedOrBlankNodeRef::BlankNode(blank_node) => self.get_encoded_blank_node(blank_node),
} }
} "http://www.w3.org/2001/XMLSchema#float" => parse_float_str(value),
"http://www.w3.org/2001/XMLSchema#double" => parse_double_str(value),
fn get_encoded_term(&self, term: TermRef<'_>) -> Result<Option<EncodedTerm>, Self::Error> { "http://www.w3.org/2001/XMLSchema#integer"
match term { | "http://www.w3.org/2001/XMLSchema#byte"
TermRef::NamedNode(named_node) => self.get_encoded_named_node(named_node), | "http://www.w3.org/2001/XMLSchema#short"
TermRef::BlankNode(blank_node) => self.get_encoded_blank_node(blank_node), | "http://www.w3.org/2001/XMLSchema#int"
TermRef::Literal(literal) => self.get_encoded_literal(literal), | "http://www.w3.org/2001/XMLSchema#long"
| "http://www.w3.org/2001/XMLSchema#unsignedByte"
| "http://www.w3.org/2001/XMLSchema#unsignedShort"
| "http://www.w3.org/2001/XMLSchema#unsignedInt"
| "http://www.w3.org/2001/XMLSchema#unsignedLong"
| "http://www.w3.org/2001/XMLSchema#positiveInteger"
| "http://www.w3.org/2001/XMLSchema#negativeInteger"
| "http://www.w3.org/2001/XMLSchema#nonPositiveInteger"
| "http://www.w3.org/2001/XMLSchema#nonNegativeInteger" => parse_integer_str(value),
"http://www.w3.org/2001/XMLSchema#decimal" => parse_decimal_str(value),
"http://www.w3.org/2001/XMLSchema#dateTime"
| "http://www.w3.org/2001/XMLSchema#dateTimeStamp" => parse_date_time_str(value),
"http://www.w3.org/2001/XMLSchema#time" => parse_time_str(value),
"http://www.w3.org/2001/XMLSchema#date" => parse_date_str(value),
"http://www.w3.org/2001/XMLSchema#gYearMonth" => parse_g_year_month_str(value),
"http://www.w3.org/2001/XMLSchema#gYear" => parse_g_year_str(value),
"http://www.w3.org/2001/XMLSchema#gMonthDay" => parse_g_month_day_str(value),
"http://www.w3.org/2001/XMLSchema#gDay" => parse_g_day_str(value),
"http://www.w3.org/2001/XMLSchema#gMonth" => parse_g_month_str(value),
"http://www.w3.org/2001/XMLSchema#duration" => parse_duration_str(value),
"http://www.w3.org/2001/XMLSchema#yearMonthDuration" => {
parse_year_month_duration_str(value)
}
"http://www.w3.org/2001/XMLSchema#dayTimeDuration" => parse_day_time_duration_str(value),
_ => None,
};
match native_encoding {
Some(term) => term,
None => {
if let Ok(value) = SmallString::try_from(value) {
EncodedTerm::SmallTypedLiteral {
value,
datatype_id: StrHash::new(datatype),
}
} else {
EncodedTerm::BigTypedLiteral {
value_id: StrHash::new(value),
datatype_id: StrHash::new(datatype),
}
}
} }
} }
}
fn get_encoded_graph_name( pub(crate) fn get_encoded_named_or_blank_node(term: NamedOrBlankNodeRef<'_>) -> EncodedTerm {
&self, match term {
name: GraphNameRef<'_>, NamedOrBlankNodeRef::NamedNode(named_node) => get_encoded_named_node(named_node),
) -> Result<Option<EncodedTerm>, Self::Error> { NamedOrBlankNodeRef::BlankNode(blank_node) => get_encoded_blank_node(blank_node),
match name {
GraphNameRef::NamedNode(named_node) => self.get_encoded_named_node(named_node),
GraphNameRef::BlankNode(blank_node) => self.get_encoded_blank_node(blank_node),
GraphNameRef::DefaultGraph => Ok(Some(EncodedTerm::DefaultGraph)),
}
} }
}
fn get_encoded_quad(&self, quad: QuadRef<'_>) -> Result<Option<EncodedQuad>, Self::Error> { pub(crate) fn get_encoded_term(term: TermRef<'_>) -> EncodedTerm {
Ok(Some(EncodedQuad { match term {
subject: if let Some(subject) = self.get_encoded_named_or_blank_node(quad.subject)? { TermRef::NamedNode(named_node) => get_encoded_named_node(named_node),
subject TermRef::BlankNode(blank_node) => get_encoded_blank_node(blank_node),
} else { TermRef::Literal(literal) => get_encoded_literal(literal),
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>; pub(crate) fn get_encoded_graph_name(name: GraphNameRef<'_>) -> EncodedTerm {
match name {
GraphNameRef::NamedNode(named_node) => get_encoded_named_node(named_node),
GraphNameRef::BlankNode(blank_node) => get_encoded_blank_node(blank_node),
GraphNameRef::DefaultGraph => EncodedTerm::DefaultGraph,
}
} }
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,74 +170,16 @@ 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
pub fn iter(&self) -> QuadIter { pub fn iter(&self) -> QuadIter {
self.quads_for_pattern(None, None, None, None) self.quads_for_pattern(None, None, None, None)
@ -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 self.storage.contains_named_graph(graph_name)
.get_encoded_named_or_blank_node(graph_name.into())?
{
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 self.storage.remove_named_graph(graph_name)
.get_encoded_named_or_blank_node(graph_name.into())?
{
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, iter: ChainedDecodingQuadIterator,
} storage: Storage,
enum QuadIterInner {
Quads {
iter: ChainedDecodingQuadIterator,
store: Store,
},
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