From aa7a23b94dd101d17e2741f3443eda494720bbaf Mon Sep 17 00:00:00 2001 From: Tpt Date: Thu, 22 Apr 2021 19:13:27 +0200 Subject: [PATCH] Makes term encoding not fail if the string is not stored --- lib/src/sparql/dataset.rs | 37 ++-- lib/src/sparql/update.rs | 128 ++++------- lib/src/storage/binary_encoder.rs | 5 +- lib/src/storage/numeric_encoder.rs | 339 ++++++++++------------------- lib/src/store.rs | 168 +++----------- 5 files changed, 215 insertions(+), 462 deletions(-) diff --git a/lib/src/sparql/dataset.rs b/lib/src/sparql/dataset.rs index 2e782308..b67641c4 100644 --- a/lib/src/sparql/dataset.rs +++ b/lib/src/sparql/dataset.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 { 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::, _>>() - }) - .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::, _>>() - }) - .transpose()?, + default: dataset.default_graph_graphs().map(|graphs| { + graphs + .iter() + .map(|g| get_encoded_graph_name(g.as_ref())) + .collect::>() + }), + named: dataset.available_named_graphs().map(|graphs| { + graphs + .iter() + .map(|g| get_encoded_named_or_blank_node(g.as_ref())) + .collect::>() + }), }; Ok(Self { storage, diff --git a/lib/src/sparql/update.rs b/lib/src/sparql/update.rs index b47bc079..2f25aecb 100644 --- a/lib/src/sparql/update.rs +++ b/lib/src/sparql/update.rs @@ -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, EvaluationError> { - Ok(Some(EncodedQuad { - subject: if let Some(subject) = match &quad.subject { + fn encode_quad_for_deletion(&mut self, quad: &Quad) -> Result { + 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], ) -> Result, 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], - ) -> Result, EvaluationError> { - Ok(match term { - NamedNodeOrVariable::NamedNode(term) => self.encode_named_node_for_deletion(term)?, + ) -> Option { + 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, 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, 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)) } - })?) + }) } } diff --git a/lib/src/storage/binary_encoder.rs b/lib/src/storage/binary_encoder.rs index 80c453ba..67746168 100644 --- a/lib/src/storage/binary_encoder.rs +++ b/lib/src/storage/binary_encoder.rs @@ -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(); diff --git a/lib/src/storage/numeric_encoder.rs b/lib/src/storage/numeric_encoder.rs index b6113a0f..cf09da09 100644 --- a/lib/src/storage/numeric_encoder.rs +++ b/lib/src/storage/numeric_encoder.rs @@ -497,246 +497,147 @@ pub(crate) trait StrLookup { pub(crate) trait StrContainer: StrLookup { fn insert_str(&self, key: StrHash, value: &str) -> Result; } - -/// 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, 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, 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, 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, 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, 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, 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, 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, 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 ReadEncoder for S { - fn get_encoded_str(&self, value: &str) -> Result, 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), } } diff --git a/lib/src/store.rs b/lib/src/store.rs index d2c5da45..2b4c0ed8 100644 --- a/lib/src/store.rs +++ b/lib/src/store.rs @@ -29,12 +29,6 @@ //! # Result::<_,Box>::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>, ) -> 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>, - predicate: Option>, - object: Option>, - graph_name: Option>, - ) -> Result< - Option<( - Option, - Option, - Option, - Option, - )>, - 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>) -> Result { - 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>) -> Result { - 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>, ) -> Result { - 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>, ) -> 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>, ) -> Result { - 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>, ) -> Result { - 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), - Empty, + iter: ChainedDecodingQuadIterator, + storage: Storage, } impl Iterator for QuadIter { type Item = Result; fn next(&mut self) -> Option> { - 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(o: Option>) -> Option> { - match o { - Some(Some(v)) => Some(Some(v)), - Some(None) => None, - None => Some(None), - } -} - #[test] fn store() -> Result<(), io::Error> { use crate::model::*;