diff --git a/contracts/okp4-cognitarium/src/contract.rs b/contracts/okp4-cognitarium/src/contract.rs index 7f7c7a9f..89f98ba0 100644 --- a/contracts/okp4-cognitarium/src/contract.rs +++ b/contracts/okp4-cognitarium/src/contract.rs @@ -53,7 +53,7 @@ pub mod execute { use crate::msg::{ DataFormat, Prefix, SimpleWhereCondition, TripleDeleteTemplate, WhereClause, WhereCondition, }; - use crate::querier::{PlanBuilder, QueryEngine}; + use crate::querier::{PlanBuilder, QueryEngine, ResolvedVariables}; use crate::rdf::PrefixMap; use crate::state::{HasCachedNamespaces, Triple}; use crate::storer::StoreEngine; @@ -120,9 +120,29 @@ pub mod execute { let mut plan_builder = PlanBuilder::new(deps.storage, &prefix_map, None); let plan = plan_builder.build_plan(&r#where)?; - let triples = QueryEngine::new(deps.storage) - .construct_triples(plan, &prefix_map, delete, plan_builder.cached_namespaces())? - .collect::>>()?; + let query_engine = QueryEngine::new(deps.storage); + let delete_templates = query_engine.make_triple_templates( + &plan, + &prefix_map, + delete, + plan_builder.cached_namespaces(), + )?; + + let triples = if r#where.is_empty() { + let empty_vars = ResolvedVariables::with_capacity(0); + delete_templates + .into_iter() + .filter_map(|tpl| match tpl.resolve(&empty_vars) { + Ok(Some(v)) => Some(Ok(v)), + Ok(None) => None, + Err(e) => Some(Err(e)), + }) + .collect::>>()? + } else { + query_engine + .construct_triples(plan, delete_templates)? + .collect::>>()? + }; let mut store = StoreEngine::new(deps.storage)?; let count = store.delete_all(&triples)?; @@ -990,6 +1010,31 @@ mod tests { 17, Uint128::from(0u128), ), + ( + DeleteData { + prefixes: vec![ + Prefix { + prefix: "core".to_string(), + namespace: "https://ontology.okp4.space/core/".to_string(), + }, + Prefix { + prefix: "thesaurus".to_string(), + namespace: "https://ontology.okp4.space/thesaurus/topic/".to_string(), + }, + ], + delete: vec![msg::TripleDeleteTemplate { + subject: VarOrNamedNode::NamedNode(Full(id.to_string())), + predicate: VarOrNamedNode::NamedNode(Prefixed("core:hasTopic".to_string())), + object: VarOrNamedNodeOrLiteral::NamedNode(Prefixed( + "thesaurus:Test".to_string(), + )), + }], + r#where: vec![], + }, + 1, + 0, + Uint128::from(6921u128), + ), ]; for case in cases { @@ -1100,24 +1145,6 @@ mod tests { }, expected: StdError::generic_err("Selected variable not found in query").into(), }, - TC { - command: DeleteData { - prefixes: vec![], - delete: vec![msg::TripleDeleteTemplate { - subject: VarOrNamedNode::NamedNode(Full( - "https://ontology.okp4.space/thesaurus/topic/Test".to_string(), - )), - predicate: VarOrNamedNode::NamedNode(Full( - "https://ontology.okp4.space/core/hasTopic".to_string(), - )), - object: VarOrNamedNodeOrLiteral::NamedNode(Full( - "https://ontology.okp4.space/thesaurus/topic/Test".to_string(), - )), - }], - r#where: vec![], - }, - expected: StdError::generic_err("Empty basic graph pattern").into(), - }, ]; for case in cases { diff --git a/contracts/okp4-cognitarium/src/querier/engine.rs b/contracts/okp4-cognitarium/src/querier/engine.rs index 9513fea9..834a90cc 100644 --- a/contracts/okp4-cognitarium/src/querier/engine.rs +++ b/contracts/okp4-cognitarium/src/querier/engine.rs @@ -78,26 +78,28 @@ impl<'a> QueryEngine<'a> { pub fn construct_triples( &'a self, plan: QueryPlan, + templates: Vec, + ) -> StdResult> { + ResolvedTripleIterator::try_new(self.eval_plan(plan), templates) + } + + pub fn make_triple_templates( + &'a self, + plan: &QueryPlan, prefixes: &HashMap, templates: Either< Vec<(VarOrNode, VarOrNamedNode, VarOrNodeOrLiteral)>, Vec<(VarOrNamedNode, VarOrNamedNode, VarOrNamedNodeOrLiteral)>, >, ns_cache: Vec, - ) -> StdResult> { + ) -> StdResult> { let mut ns_resolver: NamespaceResolver = ns_cache.into(); - let templates = match templates { + match templates { Left(tpl) => tpl .into_iter() .map(|t| { - TripleTemplate::try_new( - self.storage, - &mut ns_resolver, - &plan, - prefixes, - Left(t), - ) + TripleTemplate::try_new(self.storage, &mut ns_resolver, plan, prefixes, Left(t)) }) .collect::>>(), Right(tpl) => tpl @@ -106,15 +108,13 @@ impl<'a> QueryEngine<'a> { TripleTemplate::try_new( self.storage, &mut ns_resolver, - &plan, + plan, prefixes, Right(t), ) }) .collect::>>(), - }?; - - ResolvedTripleIterator::try_new(self.eval_plan(plan), templates) + } } pub fn eval_plan(&'a self, plan: QueryPlan) -> ResolvedVariablesIterator<'_> { diff --git a/contracts/okp4-cognitarium/src/querier/mod.rs b/contracts/okp4-cognitarium/src/querier/mod.rs index 4f068b7a..fe87d846 100644 --- a/contracts/okp4-cognitarium/src/querier/mod.rs +++ b/contracts/okp4-cognitarium/src/querier/mod.rs @@ -6,3 +6,4 @@ mod variable; pub use engine::*; pub use plan_builder::*; +pub use variable::ResolvedVariables; diff --git a/contracts/okp4-cognitarium/src/querier/plan_builder.rs b/contracts/okp4-cognitarium/src/querier/plan_builder.rs index 7b67a72b..baee369f 100644 --- a/contracts/okp4-cognitarium/src/querier/plan_builder.rs +++ b/contracts/okp4-cognitarium/src/querier/plan_builder.rs @@ -53,32 +53,27 @@ impl<'a> PlanBuilder<'a> { }) .collect::>>()?; - Self::build_from_bgp(bgp) - .map(|mut node| { - if let Some(skip) = self.skip { - node = QueryNode::Skip { - child: Box::new(node), - first: skip, - } - } - node - }) - .map(|mut node| { - if let Some(limit) = self.limit { - node = QueryNode::Limit { - child: Box::new(node), - first: limit, - } - } - node - }) - .map(|node| QueryPlan { - entrypoint: node, - variables: self.variables.clone(), - }) + let mut node = Self::build_from_bgp(bgp); + + if let Some(skip) = self.skip { + node = QueryNode::Skip { + child: Box::new(node), + first: skip, + } + } + if let Some(limit) = self.limit { + node = QueryNode::Limit { + child: Box::new(node), + first: limit, + } + } + Ok(QueryPlan { + entrypoint: node, + variables: self.variables.clone(), + }) } - fn build_from_bgp(bgp: Vec) -> StdResult { + fn build_from_bgp(bgp: Vec) -> QueryNode { bgp.into_iter() .reduce(|left: QueryNode, right: QueryNode| -> QueryNode { if left @@ -97,10 +92,9 @@ impl<'a> PlanBuilder<'a> { right: Box::new(right), } }) - .map_or_else( - || Err(StdError::generic_err("Empty basic graph pattern")), - Ok, - ) + .unwrap_or(QueryNode::Noop { + bound_variables: vec![], + }) } fn build_triple_pattern(&mut self, pattern: &TriplePattern) -> StdResult {