diff --git a/contracts/okp4-cognitarium/src/contract.rs b/contracts/okp4-cognitarium/src/contract.rs index af214d45..9a427169 100644 --- a/contracts/okp4-cognitarium/src/contract.rs +++ b/contracts/okp4-cognitarium/src/contract.rs @@ -319,6 +319,7 @@ pub mod util { }; use crate::querier::SelectResults; use crate::state::{Namespace, NamespaceResolver}; + use okp4_rdf::normalize::IdentifierIssuer; use std::collections::{BTreeMap, HashSet}; pub fn as_select_variables(patterns: &[TriplePattern]) -> Vec { @@ -347,6 +348,7 @@ pub mod util { ns_cache: Vec, ) -> StdResult { let mut ns_resolver: NamespaceResolver = ns_cache.into(); + let mut id_issuer = IdentifierIssuer::new("b", 0u128); let mut bindings: Vec> = vec![]; for solution in res.solutions { @@ -356,11 +358,14 @@ pub mod util { .map(|(name, var)| -> StdResult<(String, Value)> { Ok(( name, - var.as_value(&mut |ns_key| { - let res = ns_resolver.resolve_from_key(deps.storage, ns_key); - res.and_then(NamespaceResolver::none_as_error_middleware) - .map(|ns| ns.value) - })?, + var.as_value( + &mut |ns_key| { + let res = ns_resolver.resolve_from_key(deps.storage, ns_key); + res.and_then(NamespaceResolver::none_as_error_middleware) + .map(|ns| ns.value) + }, + &mut id_issuer, + )?, )) }) .collect::>>()?; diff --git a/contracts/okp4-cognitarium/src/querier/engine.rs b/contracts/okp4-cognitarium/src/querier/engine.rs index dc4617da..dd9e611a 100644 --- a/contracts/okp4-cognitarium/src/querier/engine.rs +++ b/contracts/okp4-cognitarium/src/querier/engine.rs @@ -1,7 +1,5 @@ -use crate::msg::{SelectItem, TriplePattern, VarOrNode, VarOrNodeOrLiteral}; -use crate::querier::mapper::{ - literal_as_object, node_as_object, node_as_predicate, node_as_subject, -}; +use crate::msg::{Node, SelectItem, TriplePattern, VarOrNode, VarOrNodeOrLiteral}; +use crate::querier::mapper::{iri_as_node, literal_as_object, node_as_predicate}; use crate::querier::plan::{PatternValue, QueryNode, QueryPlan}; use crate::querier::variable::{ResolvedVariable, ResolvedVariables}; use crate::rdf::Atom; @@ -9,6 +7,7 @@ use crate::state::{triples, Namespace, NamespaceResolver, Object, Predicate, Sub use crate::{rdf, state}; use cosmwasm_std::{Order, StdError, StdResult, Storage}; use either::{Either, Left, Right}; +use okp4_rdf::normalize::IdentifierIssuer; use std::collections::{BTreeMap, HashMap, VecDeque}; use std::iter; use std::rc::Rc; @@ -568,19 +567,19 @@ impl TripleTemplate { pattern: &TriplePattern, ) -> StdResult { Ok(TripleTemplate { - subject: Self::build_subject_pattern( + subject: Self::build_subject_template( ns_resolver, storage, prefixes, pattern.subject.clone(), )?, - predicate: Self::build_predicate_pattern( + predicate: Self::build_predicate_template( ns_resolver, storage, prefixes, pattern.predicate.clone(), )?, - object: Self::build_object_pattern( + object: Self::build_object_template( ns_resolver, storage, prefixes, @@ -645,7 +644,7 @@ impl TripleTemplate { } } - fn build_subject_pattern( + fn build_subject_template( ns_resolver: &mut NamespaceResolver, storage: &dyn Storage, prefixes: &HashMap, @@ -653,11 +652,17 @@ impl TripleTemplate { ) -> StdResult> { Ok(match value { VarOrNode::Variable(v) => Right(v), - VarOrNode::Node(n) => Left(node_as_subject(ns_resolver, storage, prefixes, n)?), + VarOrNode::Node(Node::BlankNode(b)) => Right(b), + VarOrNode::Node(Node::NamedNode(iri)) => Left(Subject::Named(iri_as_node( + ns_resolver, + storage, + prefixes, + iri, + )?)), }) } - fn build_predicate_pattern( + fn build_predicate_template( ns_resolver: &mut NamespaceResolver, storage: &dyn Storage, prefixes: &HashMap, @@ -669,7 +674,7 @@ impl TripleTemplate { }) } - fn build_object_pattern( + fn build_object_template( ns_resolver: &mut NamespaceResolver, storage: &dyn Storage, prefixes: &HashMap, @@ -677,7 +682,13 @@ impl TripleTemplate { ) -> StdResult> { Ok(match value { VarOrNodeOrLiteral::Variable(v) => Right(v), - VarOrNodeOrLiteral::Node(n) => Left(node_as_object(ns_resolver, storage, prefixes, n)?), + VarOrNodeOrLiteral::Node(Node::BlankNode(b)) => Right(b), + VarOrNodeOrLiteral::Node(Node::NamedNode(iri)) => Left(Object::Named(iri_as_node( + ns_resolver, + storage, + prefixes, + iri, + )?)), VarOrNodeOrLiteral::Literal(l) => { Left(literal_as_object(ns_resolver, storage, prefixes, l)?) } @@ -687,6 +698,7 @@ impl TripleTemplate { pub struct ResolvedAtomIterator<'a> { ns_resolver: &'a mut NamespaceResolver, + id_issuer: IdentifierIssuer, storage: &'a dyn Storage, iter: SolutionsIterator<'a>, templates: Vec, @@ -703,6 +715,7 @@ impl<'a> ResolvedAtomIterator<'a> { ) -> StdResult { Ok(Self { ns_resolver, + id_issuer: IdentifierIssuer::new("b", 0u128), storage, iter: solutions, templates: patterns @@ -733,11 +746,9 @@ impl<'a> Iterator for ResolvedAtomIterator<'a> { self.buffer.push_back(Err(err)); } Ok(vars) => { - for res in self - .templates - .iter() - .map(|template| template.resolve(self.ns_resolver, self.storage, &vars)) - { + for res in self.templates.iter().map(|template| { + template.resolve(self.ns_resolver, &mut self.id_issuer, self.storage, &vars) + }) { match res { Ok(Some(atom)) => self.buffer.push_back(Ok(atom)), Err(err) => self.buffer.push_back(Err(err)), @@ -781,6 +792,7 @@ impl AtomTemplate { pub fn resolve( &self, ns_resolver: &mut NamespaceResolver, + id_issuer: &mut IdentifierIssuer, storage: &dyn Storage, vars: &BTreeMap, ) -> StdResult> { @@ -790,7 +802,7 @@ impl AtomTemplate { .map(|ns| ns.value) }; - let subject = match self.resolve_atom_subject(resolve_ns_fn, vars)? { + let subject = match self.resolve_atom_subject(resolve_ns_fn, id_issuer, vars)? { Some(s) => s, None => return Ok(None), }; @@ -800,7 +812,7 @@ impl AtomTemplate { None => return Ok(None), }; - let value = match self.resolve_atom_value(resolve_ns_fn, vars)? { + let value = match self.resolve_atom_value(resolve_ns_fn, id_issuer, vars)? { Some(v) => v, None => return Ok(None), }; @@ -815,6 +827,7 @@ impl AtomTemplate { fn resolve_atom_subject( &self, resolve_ns_fn: &mut F, + id_issuer: &mut IdentifierIssuer, vars: &BTreeMap, ) -> StdResult> where @@ -827,7 +840,9 @@ impl AtomTemplate { &mut |value| { Ok(match value { Subject::Named(n) => rdf::Subject::NamedNode(n.as_iri(resolve_ns_fn)?), - Subject::Blank(n) => rdf::Subject::BlankNode(n), + Subject::Blank(n) => { + rdf::Subject::BlankNode(id_issuer.get_str_or_issue(n.to_string())) + } }) }, "subject", @@ -854,6 +869,7 @@ impl AtomTemplate { fn resolve_atom_value( &self, resolve_ns_fn: &mut F, + id_issuer: &mut IdentifierIssuer, vars: &BTreeMap, ) -> StdResult> where @@ -866,7 +882,9 @@ impl AtomTemplate { &mut |value| { Ok(match value { Object::Named(n) => rdf::Value::NamedNode(n.as_iri(resolve_ns_fn)?), - Object::Blank(n) => rdf::Value::BlankNode(n), + Object::Blank(n) => { + rdf::Value::BlankNode(id_issuer.get_str_or_issue(n.to_string())) + } Object::Literal(l) => match l { state::Literal::Simple { value } => rdf::Value::LiteralSimple(value), state::Literal::I18NString { value, language } => { @@ -917,7 +935,9 @@ mod test { use crate::querier::plan::PlanVariable; use crate::state; use crate::state::Object::{Literal, Named}; - use crate::state::{Node, Store, StoreStat, NAMESPACE_KEY_INCREMENT, STORE}; + use crate::state::{ + Node, Store, StoreStat, BLANK_NODE_IDENTIFIER_COUNTER, NAMESPACE_KEY_INCREMENT, STORE, + }; use crate::storer::StoreEngine; use cosmwasm_std::testing::mock_dependencies; use cosmwasm_std::{Addr, Uint128}; @@ -954,6 +974,7 @@ mod test { ) .unwrap(); NAMESPACE_KEY_INCREMENT.save(storage, &0u128).unwrap(); + BLANK_NODE_IDENTIFIER_COUNTER.save(storage, &0u128).unwrap(); let data = read_test_data("sample.rdf.xml"); let buf = BufReader::new(data.as_slice()); let mut reader = TripleReader::new(&okp4_rdf::serde::DataFormat::RDFXml, buf); @@ -1295,33 +1316,30 @@ mod test { #[test] fn for_loop_join_iter() { struct TestCase { - left: Vec, - right: Vec, - expects: Vec<(String, String)>, + left: Vec, + right: Vec, + expects: Vec<(u128, u128)>, } let cases = vec![ TestCase { left: vec![], - right: vec!["1".to_string(), "2".to_string()], + right: vec![0u128, 1u128], expects: vec![], }, TestCase { - left: vec!["A".to_string()], - right: vec!["1".to_string(), "2".to_string()], - expects: vec![ - ("A".to_string(), "1".to_string()), - ("A".to_string(), "2".to_string()), - ], + left: vec![2u128], + right: vec![0u128, 1u128], + expects: vec![(2u128, 0u128), (2u128, 1u128)], }, TestCase { - left: vec!["A".to_string(), "B".to_string()], - right: vec!["1".to_string(), "2".to_string()], + left: vec![2u128, 3u128], + right: vec![0u128, 1u128], expects: vec![ - ("A".to_string(), "1".to_string()), - ("A".to_string(), "2".to_string()), - ("B".to_string(), "1".to_string()), - ("B".to_string(), "2".to_string()), + (2u128, 0u128), + (2u128, 1u128), + (3u128, 0u128), + (3u128, 1u128), ], }, ]; @@ -1330,13 +1348,13 @@ mod test { let result = ForLoopJoinIterator::new( Box::new(case.left.iter().map(|v| { let mut vars = ResolvedVariables::with_capacity(3); - vars.merge_index(1, ResolvedVariable::Subject(Subject::Blank(v.clone()))); + vars.merge_index(1, ResolvedVariable::Subject(Subject::Blank(*v))); Ok(vars) })), Rc::new(|input| { Box::new(case.right.iter().map(move |v| { let mut vars = input.clone(); - vars.merge_index(2, ResolvedVariable::Subject(Subject::Blank(v.clone()))); + vars.merge_index(2, ResolvedVariable::Subject(Subject::Blank(*v))); Ok(vars) })) }), @@ -1349,8 +1367,8 @@ mod test { .iter() .map(|(v1, v2)| { let mut vars = ResolvedVariables::with_capacity(3); - vars.merge_index(1, ResolvedVariable::Subject(Subject::Blank(v1.clone()))); - vars.merge_index(2, ResolvedVariable::Subject(Subject::Blank(v2.clone()))); + vars.merge_index(1, ResolvedVariable::Subject(Subject::Blank(*v1))); + vars.merge_index(2, ResolvedVariable::Subject(Subject::Blank(*v2))); vars }) .collect(); @@ -1362,38 +1380,35 @@ mod test { #[test] fn cartesian_join_iter() { struct TestCase { - left: Vec, - right: Vec, - expects: Vec>, + left: Vec, + right: Vec, + expects: Vec>, } let cases = vec![ TestCase { left: vec![], - right: vec!["1".to_string(), "2".to_string()], + right: vec![0u128, 1u128], expects: vec![], }, TestCase { - left: vec!["1".to_string(), "2".to_string()], + left: vec![0u128, 1u128], right: vec![], expects: vec![], }, TestCase { - left: vec!["A".to_string()], - right: vec!["1".to_string(), "2".to_string()], - expects: vec![ - vec!["1".to_string(), "A".to_string()], - vec!["2".to_string(), "A".to_string()], - ], + left: vec![2u128], + right: vec![0u128, 1u128], + expects: vec![vec![0u128, 2u128], vec![1u128, 2u128]], }, TestCase { - left: vec!["A".to_string(), "B".to_string()], - right: vec!["1".to_string(), "2".to_string()], + left: vec![2u128, 3u128], + right: vec![0u128, 1u128], expects: vec![ - vec!["1".to_string(), "A".to_string()], - vec!["2".to_string(), "A".to_string()], - vec!["1".to_string(), "B".to_string()], - vec!["2".to_string(), "B".to_string()], + vec![0u128, 2u128], + vec![1u128, 2u128], + vec![0u128, 3u128], + vec![1u128, 3u128], ], }, ]; @@ -1404,13 +1419,13 @@ mod test { .iter() .map(|v| { let mut vars = ResolvedVariables::with_capacity(2); - vars.merge_index(0, ResolvedVariable::Subject(Subject::Blank(v.clone()))); + vars.merge_index(0, ResolvedVariable::Subject(Subject::Blank(*v))); vars }) .collect(), Box::new(case.left.iter().map(|v| { let mut vars = ResolvedVariables::with_capacity(2); - vars.merge_index(1, ResolvedVariable::Subject(Subject::Blank(v.clone()))); + vars.merge_index(1, ResolvedVariable::Subject(Subject::Blank(*v))); Ok(vars) })), VecDeque::new(), @@ -1424,10 +1439,10 @@ mod test { .map(|v| { let mut vars = ResolvedVariables::with_capacity(2); if let Some(val) = v.get(0) { - vars.merge_index(0, ResolvedVariable::Subject(Subject::Blank(val.clone()))); + vars.merge_index(0, ResolvedVariable::Subject(Subject::Blank(*val))); } if let Some(val) = v.get(1) { - vars.merge_index(1, ResolvedVariable::Subject(Subject::Blank(val.clone()))); + vars.merge_index(1, ResolvedVariable::Subject(Subject::Blank(*val))); } vars }) @@ -1439,12 +1454,12 @@ mod test { #[test] fn triple_pattern_iter_compute_io() { - let t_subject = Subject::Blank("s".to_string()); + let t_subject = Subject::Blank(0u128); let t_predicate = state::Node { namespace: 0u128, value: "whatever".to_string(), }; - let t_object = Object::Blank("o".to_string()); + let t_object = Object::Blank(1u128); let mut variables = ResolvedVariables::with_capacity(6); variables.merge_index(1, ResolvedVariable::Subject(t_subject.clone())); @@ -1523,7 +1538,7 @@ mod test { predicate: PatternValue::Variable(4), object: PatternValue::Variable(5), expects: Some(( - (Some(Subject::Blank("o".to_string())), None, None), + (Some(Subject::Blank(1u128)), None, None), (false, false), (None, Some(4), Some(5)), )), diff --git a/contracts/okp4-cognitarium/src/querier/mapper.rs b/contracts/okp4-cognitarium/src/querier/mapper.rs index c7785b52..6daf4098 100644 --- a/contracts/okp4-cognitarium/src/querier/mapper.rs +++ b/contracts/okp4-cognitarium/src/querier/mapper.rs @@ -1,22 +1,10 @@ use crate::msg::{Literal, Node, IRI}; use crate::state; -use crate::state::{NamespaceResolver, Object, Predicate, Subject}; +use crate::state::{NamespaceResolver, Object, Predicate}; use cosmwasm_std::{StdError, StdResult, Storage}; use okp4_rdf::uri::{expand_uri, explode_iri}; use std::collections::HashMap; -pub fn node_as_subject( - ns_resolver: &mut NamespaceResolver, - storage: &dyn Storage, - prefixes: &HashMap, - node: Node, -) -> StdResult { - Ok(match node { - Node::NamedNode(iri) => Subject::Named(iri_as_node(ns_resolver, storage, prefixes, iri)?), - Node::BlankNode(blank) => Subject::Blank(blank), - }) -} - pub fn node_as_predicate( ns_resolver: &mut NamespaceResolver, storage: &dyn Storage, @@ -31,18 +19,6 @@ pub fn node_as_predicate( } } -pub fn node_as_object( - ns_resolver: &mut NamespaceResolver, - storage: &dyn Storage, - prefixes: &HashMap, - node: Node, -) -> StdResult { - Ok(match node { - Node::NamedNode(iri) => Object::Named(iri_as_node(ns_resolver, storage, prefixes, iri)?), - Node::BlankNode(blank) => Object::Blank(blank), - }) -} - pub fn literal_as_object( ns_resolver: &mut NamespaceResolver, storage: &dyn Storage, diff --git a/contracts/okp4-cognitarium/src/querier/variable.rs b/contracts/okp4-cognitarium/src/querier/variable.rs index d9a37f47..1c04aa41 100644 --- a/contracts/okp4-cognitarium/src/querier/variable.rs +++ b/contracts/okp4-cognitarium/src/querier/variable.rs @@ -1,6 +1,7 @@ use crate::msg::{Value, IRI}; use crate::state::{Literal, Object, Predicate, Subject}; use cosmwasm_std::StdResult; +use okp4_rdf::normalize::IdentifierIssuer; #[derive(Eq, PartialEq, Debug, Clone)] pub enum ResolvedVariable { @@ -48,7 +49,7 @@ impl ResolvedVariable { }) } - pub fn as_value(&self, ns_fn: &mut F) -> StdResult + pub fn as_value(&self, ns_fn: &mut F, id_issuer: &mut IdentifierIssuer) -> StdResult where F: FnMut(u128) -> StdResult, { @@ -58,7 +59,7 @@ impl ResolvedVariable { value: IRI::Full(iri), })?, Subject::Blank(blank) => Value::BlankNode { - value: blank.to_string(), + value: id_issuer.get_str_or_issue(blank.to_string()), }, }, ResolvedVariable::Predicate(predicate) => { @@ -71,7 +72,7 @@ impl ResolvedVariable { value: IRI::Full(named.as_iri(ns_fn)?), }, Object::Blank(blank) => Value::BlankNode { - value: blank.to_string(), + value: id_issuer.get_str_or_issue(blank.to_string()), }, Object::Literal(literal) => match literal { Literal::Simple { value } => Value::Literal { @@ -155,9 +156,9 @@ mod tests { fn conversions() { let cases: Vec<(Option, Option, Option)> = vec![ ( - Some(Subject::Blank("_".to_string())), + Some(Subject::Blank(0u128)), None, - Some(Object::Blank("_".to_string())), + Some(Object::Blank(0u128)), ), ( Some(Subject::Named(Node { @@ -226,9 +227,9 @@ mod tests { }), ), ( - ResolvedVariable::Subject(Subject::Blank("_".to_string())), + ResolvedVariable::Subject(Subject::Blank(0u128)), Ok(Value::BlankNode { - value: "_".to_string(), + value: "b0".to_string(), }), ), ( @@ -250,9 +251,9 @@ mod tests { }), ), ( - ResolvedVariable::Object(Object::Blank("_".to_string())), + ResolvedVariable::Object(Object::Blank(0u128)), Ok(Value::BlankNode { - value: "_".to_string(), + value: "b0".to_string(), }), ), ( @@ -292,61 +293,38 @@ mod tests { ), ]; + let mut id_issuer = IdentifierIssuer::new("b", 0u128); for (var, expected) in cases { - assert_eq!(var.as_value(&mut ns), expected) + assert_eq!(var.as_value(&mut ns, &mut id_issuer), expected) } } #[test] fn merged_variables() { let mut vars1 = ResolvedVariables::with_capacity(3); - vars1.merge_index( - 0, - ResolvedVariable::Object(Object::Blank("foo".to_string())), - ); - vars1.merge_index( - 2, - ResolvedVariable::Object(Object::Blank("bar".to_string())), - ); + vars1.merge_index(0, ResolvedVariable::Object(Object::Blank(0u128))); + vars1.merge_index(2, ResolvedVariable::Object(Object::Blank(1u128))); let mut vars2 = ResolvedVariables::with_capacity(3); - vars2.merge_index( - 1, - ResolvedVariable::Object(Object::Blank("pop".to_string())), - ); - vars2.merge_index( - 2, - ResolvedVariable::Object(Object::Blank("bar".to_string())), - ); + vars2.merge_index(1, ResolvedVariable::Object(Object::Blank(2u128))); + vars2.merge_index(2, ResolvedVariable::Object(Object::Blank(1u128))); assert_eq!( vars2.get(1), - &Some(ResolvedVariable::Object(Object::Blank("pop".to_string()))) + &Some(ResolvedVariable::Object(Object::Blank(2u128))) ); assert_eq!(vars1.get(1), &None); let mut expected_result = ResolvedVariables::with_capacity(3); - expected_result.merge_index( - 0, - ResolvedVariable::Object(Object::Blank("foo".to_string())), - ); - expected_result.merge_index( - 1, - ResolvedVariable::Object(Object::Blank("pop".to_string())), - ); - expected_result.merge_index( - 2, - ResolvedVariable::Object(Object::Blank("bar".to_string())), - ); + expected_result.merge_index(0, ResolvedVariable::Object(Object::Blank(0u128))); + expected_result.merge_index(1, ResolvedVariable::Object(Object::Blank(2u128))); + expected_result.merge_index(2, ResolvedVariable::Object(Object::Blank(1u128))); let result = vars1.merge_with(&vars2); assert_eq!(result, Some(expected_result)); let mut vars3 = ResolvedVariables::with_capacity(3); - vars3.merge_index( - 1, - ResolvedVariable::Object(Object::Blank("pop".to_string())), - ); + vars3.merge_index(1, ResolvedVariable::Object(Object::Blank(2u128))); vars3.merge_index( 2, ResolvedVariable::Predicate(Node { diff --git a/contracts/okp4-cognitarium/src/storer/engine.rs b/contracts/okp4-cognitarium/src/storer/engine.rs index c8f480e9..71564f95 100644 --- a/contracts/okp4-cognitarium/src/storer/engine.rs +++ b/contracts/okp4-cognitarium/src/storer/engine.rs @@ -1,9 +1,11 @@ use crate::error::StoreError; use crate::state::{ - triples, Literal, NamespaceBatchService, Node, Object, Store, Subject, Triple, STORE, + triples, Literal, NamespaceBatchService, Node, Object, Store, Subject, Triple, + BLANK_NODE_IDENTIFIER_COUNTER, BLANK_NODE_SIZE, STORE, }; use crate::ContractError; use cosmwasm_std::{StdError, StdResult, Storage, Uint128}; +use okp4_rdf::normalize::IdentifierIssuer; use okp4_rdf::serde::TripleReader; use okp4_rdf::uri::explode_iri; use rio_api::model; @@ -15,6 +17,7 @@ pub struct StoreEngine<'a> { storage: &'a mut dyn Storage, store: Store, ns_batch_svc: NamespaceBatchService, + blank_node_id_issuer: IdentifierIssuer, initial_triple_count: Uint128, initial_byte_size: Uint128, } @@ -22,11 +25,13 @@ pub struct StoreEngine<'a> { impl<'a> StoreEngine<'a> { pub fn new(storage: &'a mut dyn Storage) -> StdResult { let store = STORE.load(storage)?; + let blank_node_id_counter = BLANK_NODE_IDENTIFIER_COUNTER.load(storage)?; let ns_batch_svc = NamespaceBatchService::new(storage)?; Ok(Self { storage, store: store.clone(), ns_batch_svc, + blank_node_id_issuer: IdentifierIssuer::new("", blank_node_id_counter), initial_triple_count: store.stat.triple_count, initial_byte_size: store.stat.byte_size, }) @@ -53,11 +58,15 @@ impl<'a> StoreEngine<'a> { ))?; } - let triple = Self::rio_to_triple(t, &mut |ns_str| { - self.ns_batch_svc - .resolve_or_allocate(self.storage, ns_str) - .map(|ns| ns.key) - })?; + let triple = Self::rio_to_triple( + t, + &mut |ns_str| { + self.ns_batch_svc + .resolve_or_allocate(self.storage, ns_str) + .map(|ns| ns.key) + }, + &mut self.blank_node_id_issuer, + )?; let t_size = Uint128::from(self.triple_size(&triple).map_err(ContractError::Std)? as u128); if t_size > self.store.limits.max_triple_byte_size { Err(StoreError::TripleByteSize( @@ -159,6 +168,8 @@ impl<'a> StoreEngine<'a> { self.store.stat.namespace_count -= Uint128::new(ns_diff.neg() as u128); } + BLANK_NODE_IDENTIFIER_COUNTER.save(self.storage, &self.blank_node_id_issuer.counter)?; + STORE.save(self.storage, &self.store)?; let count_diff = self @@ -173,24 +184,34 @@ impl<'a> StoreEngine<'a> { Ok(count_diff) } - fn rio_to_triple(triple: model::Triple<'_>, ns_fn: &mut F) -> StdResult + fn rio_to_triple( + triple: model::Triple<'_>, + ns_fn: &mut F, + id_issuer: &mut IdentifierIssuer, + ) -> StdResult where F: FnMut(String) -> StdResult, { Ok(Triple { - subject: Self::rio_to_subject(triple.subject, ns_fn)?, + subject: Self::rio_to_subject(triple.subject, ns_fn, id_issuer)?, predicate: Self::rio_to_node(triple.predicate, ns_fn)?, - object: Self::rio_to_object(triple.object, ns_fn)?, + object: Self::rio_to_object(triple.object, ns_fn, id_issuer)?, }) } - fn rio_to_subject(subject: model::Subject<'_>, ns_fn: &mut F) -> StdResult + fn rio_to_subject( + subject: model::Subject<'_>, + ns_fn: &mut F, + id_issuer: &mut IdentifierIssuer, + ) -> StdResult where F: FnMut(String) -> StdResult, { match subject { model::Subject::NamedNode(node) => Self::rio_to_node(node, ns_fn).map(Subject::Named), - model::Subject::BlankNode(node) => Ok(Subject::Blank(node.id.to_string())), + model::Subject::BlankNode(node) => Ok(Subject::Blank( + id_issuer.get_n_or_issue(node.id.to_string()), + )), model::Subject::Triple(_) => Err(StdError::generic_err("RDF star syntax unsupported")), } } @@ -206,12 +227,18 @@ impl<'a> StoreEngine<'a> { }) } - fn rio_to_object(object: Term<'_>, ns_fn: &mut F) -> StdResult + fn rio_to_object( + object: Term<'_>, + ns_fn: &mut F, + id_issuer: &mut IdentifierIssuer, + ) -> StdResult where F: FnMut(String) -> StdResult, { match object { - Term::BlankNode(node) => Ok(Object::Blank(node.id.to_string())), + Term::BlankNode(node) => { + Ok(Object::Blank(id_issuer.get_n_or_issue(node.id.to_string()))) + } Term::NamedNode(node) => Self::rio_to_node(node, ns_fn).map(Object::Named), Term::Literal(literal) => Self::rio_to_literal(literal, ns_fn).map(Object::Literal), Term::Triple(_) => Err(StdError::generic_err("RDF star syntax unsupported")), @@ -248,7 +275,7 @@ impl<'a> StoreEngine<'a> { fn subject_size(&mut self, subject: &Subject) -> StdResult { match subject { Subject::Named(n) => self.node_size(n), - Subject::Blank(n) => Ok(n.len()), + Subject::Blank(_) => Ok(BLANK_NODE_SIZE), } } @@ -266,7 +293,7 @@ impl<'a> StoreEngine<'a> { fn object_size(&mut self, object: &Object) -> StdResult { Ok(match object { - Object::Blank(n) => n.len(), + Object::Blank(_) => BLANK_NODE_SIZE, Object::Named(n) => self.node_size(n)?, Object::Literal(l) => match l { Literal::Simple { value } => value.len(),