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::EvaluationError;
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 std::cell::RefCell;
@ -18,28 +19,18 @@ pub(crate) struct DatasetView {
impl DatasetView {
pub fn new(storage: Storage, dataset: &QueryDataset) -> Result<Self, EvaluationError> {
let dataset = EncodedDatasetSpec {
default: dataset
.default_graph_graphs()
.map(|graphs| {
graphs
.iter()
.flat_map(|g| storage.get_encoded_graph_name(g.as_ref()).transpose())
.collect::<Result<Vec<_>, _>>()
})
.transpose()?,
named: dataset
.available_named_graphs()
.map(|graphs| {
graphs
.iter()
.flat_map(|g| {
storage
.get_encoded_named_or_blank_node(g.as_ref())
.transpose()
})
.collect::<Result<Vec<_>, _>>()
})
.transpose()?,
default: dataset.default_graph_graphs().map(|graphs| {
graphs
.iter()
.map(|g| get_encoded_graph_name(g.as_ref()))
.collect::<Vec<_>>()
}),
named: dataset.available_named_graphs().map(|graphs| {
graphs
.iter()
.map(|g| get_encoded_named_or_blank_node(g.as_ref()))
.collect::<Vec<_>>()
}),
};
Ok(Self {
storage,

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

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

@ -497,246 +497,147 @@ pub(crate) trait StrLookup {
pub(crate) trait StrContainer: StrLookup {
fn insert_str(&self, key: StrHash, value: &str) -> Result<bool, Self::Error>;
}
/// Tries to encode a term based on the existing strings (does not insert anything)
pub(crate) trait ReadEncoder: StrLookup {
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);
},
}))
pub(crate) fn get_encoded_named_node(named_node: NamedNodeRef<'_>) -> EncodedTerm {
EncodedTerm::NamedNode {
iri_id: StrHash::new(named_node.as_str()),
}
}
fn get_encoded_blank_node(
&self,
blank_node: BlankNodeRef<'_>,
) -> Result<Option<EncodedTerm>, Self::Error> {
Ok(Some(if let Some(id) = blank_node.id() {
EncodedTerm::NumericalBlankNode { id }
pub(crate) fn get_encoded_blank_node(blank_node: BlankNodeRef<'_>) -> EncodedTerm {
if let Some(id) = blank_node.id() {
EncodedTerm::NumericalBlankNode { id }
} else {
let id = blank_node.as_str();
if let Ok(id) = id.try_into() {
EncodedTerm::SmallBlankNode(id)
} else {
let id = blank_node.as_str();
if let Ok(id) = id.try_into() {
EncodedTerm::SmallBlankNode(id)
} else {
EncodedTerm::BigBlankNode {
id_id: if let Some(id_id) = self.get_encoded_str(id)? {
id_id
} else {
return Ok(None);
},
}
EncodedTerm::BigBlankNode {
id_id: StrHash::new(id),
}
}))
}
}
}
fn get_encoded_literal(
&self,
literal: LiteralRef<'_>,
) -> Result<Option<EncodedTerm>, Self::Error> {
let value = literal.value();
let datatype = literal.datatype().as_str();
Ok(Some(
match match datatype {
"http://www.w3.org/1999/02/22-rdf-syntax-ns#langString" => {
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)
pub(crate) fn get_encoded_literal(literal: LiteralRef<'_>) -> EncodedTerm {
let value = literal.value();
let datatype = literal.datatype().as_str();
let native_encoding = match datatype {
"http://www.w3.org/1999/02/22-rdf-syntax-ns#langString" => {
if let Some(language) = literal.language() {
Some(if let Ok(value) = SmallString::try_from(value) {
if let Ok(language) = SmallString::try_from(language) {
EncodedTerm::SmallSmallLangStringLiteral { value, language }
} else {
EncodedTerm::BigStringLiteral {
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 {
EncodedTerm::SmallBigLangStringLiteral {
value,
datatype_id: if let Some(datatype_id) =
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);
},
language_id: StrHash::new(language),
}
}
} 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),
})
}
}
fn get_encoded_term(&self, term: TermRef<'_>) -> Result<Option<EncodedTerm>, Self::Error> {
match term {
TermRef::NamedNode(named_node) => self.get_encoded_named_node(named_node),
TermRef::BlankNode(blank_node) => self.get_encoded_blank_node(blank_node),
TermRef::Literal(literal) => self.get_encoded_literal(literal),
"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,
};
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(
&self,
name: GraphNameRef<'_>,
) -> Result<Option<EncodedTerm>, Self::Error> {
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)),
}
pub(crate) fn get_encoded_named_or_blank_node(term: NamedOrBlankNodeRef<'_>) -> EncodedTerm {
match term {
NamedOrBlankNodeRef::NamedNode(named_node) => get_encoded_named_node(named_node),
NamedOrBlankNodeRef::BlankNode(blank_node) => get_encoded_blank_node(blank_node),
}
}
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);
},
}))
pub(crate) fn get_encoded_term(term: TermRef<'_>) -> EncodedTerm {
match term {
TermRef::NamedNode(named_node) => get_encoded_named_node(named_node),
TermRef::BlankNode(blank_node) => get_encoded_blank_node(blank_node),
TermRef::Literal(literal) => get_encoded_literal(literal),
}
}
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 {
fn get_encoded_str(&self, value: &str) -> Result<Option<StrHash>, Self::Error> {
let key = StrHash::new(value);
Ok(if self.contains_str(key)? {
Some(key)
} else {
None
})
pub(crate) fn get_encoded_quad(quad: QuadRef<'_>) -> EncodedQuad {
EncodedQuad {
subject: get_encoded_named_or_blank_node(quad.subject),
predicate: get_encoded_named_node(quad.predicate),
object: get_encoded_term(quad.object),
graph_name: get_encoded_graph_name(quad.graph_name),
}
}

@ -29,12 +29,6 @@
//! # 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::model::*;
use crate::sparql::{
@ -42,13 +36,20 @@ use crate::sparql::{
UpdateOptions,
};
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::TransactionError;
pub use crate::storage::UnabortableTransactionError;
use crate::storage::{
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).
/// Allows to query and update it using SPARQL.
@ -169,74 +170,16 @@ impl Store {
graph_name: Option<GraphNameRef<'_>>,
) -> QuadIter {
QuadIter {
inner: match self.get_encoded_quad_pattern(subject, predicate, object, graph_name) {
Ok(Some((subject, predicate, object, graph_name))) => QuadIterInner::Quads {
iter: self
.storage
.quads_for_pattern(subject, predicate, object, graph_name),
store: self.clone(),
},
Ok(None) => QuadIterInner::Empty,
Err(error) => QuadIterInner::Error(once(error)),
},
iter: self.storage.quads_for_pattern(
subject.map(|s| get_encoded_named_or_blank_node(s)),
predicate.map(|p| get_encoded_named_node(p)),
object.map(|o| get_encoded_term(o)),
graph_name.map(|g| get_encoded_graph_name(g)),
),
storage: self.storage.clone(),
}
}
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
pub fn iter(&self) -> QuadIter {
self.quads_for_pattern(None, None, None, None)
@ -244,11 +187,8 @@ impl Store {
/// Checks if this store contains a given quad
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())? {
self.storage.contains(&quad)
} else {
Ok(false)
}
let quad = get_encoded_quad(quad.into());
self.storage.contains(&quad)
}
/// 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.
/// 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> {
if let Some(quad) = self.storage.get_encoded_quad(quad.into())? {
self.storage.remove(&quad)
} else {
Ok(false)
}
let quad = get_encoded_quad(quad.into());
self.storage.remove(&quad)
}
/// Dumps a store graph into a file.
@ -537,14 +474,8 @@ impl Store {
&self,
graph_name: impl Into<NamedOrBlankNodeRef<'a>>,
) -> Result<bool, io::Error> {
if let Some(graph_name) = self
.storage
.get_encoded_named_or_blank_node(graph_name.into())?
{
self.storage.contains_named_graph(graph_name)
} else {
Ok(false)
}
let graph_name = get_encoded_named_or_blank_node(graph_name.into());
self.storage.contains_named_graph(graph_name)
}
/// Inserts a graph into this store
@ -592,11 +523,8 @@ impl Store {
&self,
graph_name: impl Into<GraphNameRef<'a>>,
) -> Result<(), io::Error> {
if let Some(graph_name) = self.storage.get_encoded_graph_name(graph_name.into())? {
self.storage.clear_graph(graph_name)
} else {
Ok(())
}
let graph_name = get_encoded_graph_name(graph_name.into());
self.storage.clear_graph(graph_name)
}
/// Removes a graph from this store.
@ -623,14 +551,8 @@ impl Store {
&self,
graph_name: impl Into<NamedOrBlankNodeRef<'a>>,
) -> Result<bool, io::Error> {
if let Some(graph_name) = self
.storage
.get_encoded_named_or_blank_node(graph_name.into())?
{
self.storage.remove_named_graph(graph_name)
} else {
Ok(false)
}
let graph_name = get_encoded_named_or_blank_node(graph_name.into());
self.storage.remove_named_graph(graph_name)
}
/// Clears the store.
@ -733,7 +655,6 @@ impl Transaction<'_> {
/// use oxigraph::store::{Store, ConflictableTransactionError};
/// use oxigraph::io::DatasetFormat;
/// use oxigraph::model::*;
/// use oxigraph::store::ConflictableTransactionError;
///
/// let store = Store::new()?;
///
@ -784,11 +705,8 @@ impl Transaction<'_> {
&self,
quad: impl Into<QuadRef<'a>>,
) -> Result<bool, UnabortableTransactionError> {
if let Some(quad) = self.storage.get_encoded_quad(quad.into())? {
self.storage.remove(&quad)
} else {
Ok(false)
}
let quad = get_encoded_quad(quad.into());
self.storage.remove(&quad)
}
/// Inserts a graph into this store during the transaction
@ -805,30 +723,18 @@ impl Transaction<'_> {
/// An iterator returning the quads contained in a [`Store`].
pub struct QuadIter {
inner: QuadIterInner,
}
enum QuadIterInner {
Quads {
iter: ChainedDecodingQuadIterator,
store: Store,
},
Error(Once<io::Error>),
Empty,
iter: ChainedDecodingQuadIterator,
storage: Storage,
}
impl Iterator for QuadIter {
type Item = Result<Quad, io::Error>;
fn next(&mut self) -> Option<Result<Quad, io::Error>> {
match &mut self.inner {
QuadIterInner::Quads { iter, store } => Some(match iter.next()? {
Ok(quad) => store.storage.decode_quad(&quad).map_err(|e| e.into()),
Err(error) => Err(error),
}),
QuadIterInner::Error(iter) => iter.next().map(Err),
QuadIterInner::Empty => None,
}
Some(match self.iter.next()? {
Ok(quad) => self.storage.decode_quad(&quad).map_err(|e| e.into()),
Err(error) => Err(error),
})
}
}
@ -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]
fn store() -> Result<(), io::Error> {
use crate::model::*;

Loading…
Cancel
Save