From f15d8228c8a92efcb8532152e15eaffabe71fe23 Mon Sep 17 00:00:00 2001 From: Arnaud Mimart <33665250+amimart@users.noreply.github.com> Date: Wed, 28 Feb 2024 00:10:41 +0100 Subject: [PATCH] feat(cognitarium)!: rework construct clause based on template --- contracts/okp4-cognitarium/src/contract.rs | 327 +++++++++--------- contracts/okp4-cognitarium/src/msg.rs | 63 +++- .../okp4-cognitarium/src/querier/engine.rs | 27 +- contracts/okp4-cognitarium/src/rdf/mapper.rs | 15 +- 4 files changed, 229 insertions(+), 203 deletions(-) diff --git a/contracts/okp4-cognitarium/src/contract.rs b/contracts/okp4-cognitarium/src/contract.rs index 5af05a51..8da4b633 100644 --- a/contracts/okp4-cognitarium/src/contract.rs +++ b/contracts/okp4-cognitarium/src/contract.rs @@ -50,13 +50,12 @@ pub fn execute( pub mod execute { use super::*; - use crate::msg::{ - DataFormat, HasVariables, Prefix, TripleDeleteTemplate, TriplePattern, WhereClause, - }; + use crate::msg::{DataFormat, HasVariables, Prefix, TripleDeleteTemplate, WhereClause}; use crate::querier::{PlanBuilder, QueryEngine}; use crate::rdf::PrefixMap; use crate::state::HasCachedNamespaces; use crate::storer::StoreEngine; + use cosmwasm_std::Uint128; use okp4_rdf::serde::TripleReader; use std::io::BufReader; @@ -98,7 +97,7 @@ pub mod execute { if delete.is_empty() { return Ok(Response::new() .add_attribute("action", "delete") - .add_attribute("triple_count", 0)); + .add_attribute("triple_count", Uint128::from(0u128))); } let prefix_map = ::from(prefixes).into_inner(); @@ -228,12 +227,15 @@ pub mod query { let plan = plan_builder.build_plan(&r#where)?; let atoms = QueryEngine::new(deps.storage) - .select(plan, util::as_select_variables(&select)) + .select(plan, select.as_select_item()) .and_then(|res| { res.solutions.resolve_atoms( deps.storage, &prefix_map, - select, + select + .into_iter() + .map(|p| (p.subject, p.predicate, p.object)) + .collect(), plan_builder.cached_namespaces(), ) })?; @@ -271,23 +273,27 @@ pub mod query { prefixes, r#where, } = query; - let patterns: Vec = if construct.is_empty() { - util::as_triple_patterns(&r#where)? - } else { - construct - }; + if construct.is_empty() { + return Ok(ConstructResponse { + format, + data: Binary::from(vec![]), + }); + } let prefix_map = ::from(prefixes).into_inner(); let mut plan_builder = PlanBuilder::new(deps.storage, &prefix_map, None); let plan = plan_builder.build_plan(&r#where)?; let atoms = QueryEngine::new(deps.storage) - .select(plan, patterns.as_select_item()) + .select(plan, construct.as_select_item()) .and_then(|res| { res.solutions.resolve_atoms( deps.storage, &prefix_map, - patterns, + construct + .into_iter() + .map(|t| (t.subject, t.predicate, t.object)) + .collect(), plan_builder.cached_namespaces(), ) })?; @@ -372,8 +378,8 @@ mod tests { use crate::msg::{ ConstructQuery, ConstructResponse, DescribeQuery, DescribeResponse, Head, Literal, Prefix, Results, SelectItem, SelectQuery, SelectResponse, StoreLimitsInput, - StoreLimitsInputBuilder, StoreResponse, Value, VarOrNamedNode, VarOrNode, - VarOrNodeOrLiteral, WhereCondition, + StoreLimitsInputBuilder, StoreResponse, Value, VarOrNamedNode, VarOrNamedNodeOrLiteral, + VarOrNode, VarOrNodeOrLiteral, WhereCondition, }; use crate::state::{ namespaces, triples, Namespace, Node, Object, StoreLimits, StoreStat, Subject, Triple, @@ -756,26 +762,26 @@ mod tests { ( DeleteData { prefixes: vec![], - delete: vec![msg::TriplePattern { - subject: VarOrNode::Node(NamedNode(Full( + delete: vec![msg::TripleDeleteTemplate { + subject: VarOrNamedNode::NamedNode(Full( "https://ontology.okp4.space/dataverse/dataspace/metadata/unknown" .to_string(), - ))), - predicate: VarOrNode::Node(NamedNode(Full( + )), + predicate: VarOrNamedNode::NamedNode(Full( "https://ontology.okp4.space/core/hasTopic".to_string(), - ))), - object: VarOrNodeOrLiteral::Node(NamedNode(Full( + )), + object: VarOrNamedNodeOrLiteral::NamedNode(Full( "https://ontology.okp4.space/thesaurus/topic/Test".to_string(), - ))), + )), }], r#where: vec![WhereCondition::Simple(TriplePattern(msg::TriplePattern { subject: VarOrNode::Node(NamedNode(Full( "https://ontology.okp4.space/dataverse/dataspace/metadata/unknown" .to_string(), ))), - predicate: VarOrNode::Node(NamedNode(Full( + predicate: VarOrNamedNode::NamedNode(Full( "https://ontology.okp4.space/core/hasTopic".to_string(), - ))), + )), object: VarOrNodeOrLiteral::Node(NamedNode(Full( "https://ontology.okp4.space/thesaurus/topic/Test".to_string(), ))), @@ -788,20 +794,20 @@ mod tests { ( DeleteData { prefixes: vec![], - delete: vec![msg::TriplePattern { - subject: VarOrNode::Node(NamedNode(Full(id.to_string()))), - predicate: VarOrNode::Node(NamedNode(Full( + delete: vec![msg::TripleDeleteTemplate { + subject: VarOrNamedNode::NamedNode(Full(id.to_string())), + predicate: VarOrNamedNode::NamedNode(Full( "https://ontology.okp4.space/core/hasTopic".to_string(), - ))), - object: VarOrNodeOrLiteral::Node(NamedNode(Full( + )), + object: VarOrNamedNodeOrLiteral::NamedNode(Full( "https://ontology.okp4.space/thesaurus/topic/Test".to_string(), - ))), + )), }], r#where: vec![WhereCondition::Simple(TriplePattern(msg::TriplePattern { subject: VarOrNode::Node(NamedNode(Full(id.to_string()))), - predicate: VarOrNode::Node(NamedNode(Full( + predicate: VarOrNamedNode::NamedNode(Full( "https://ontology.okp4.space/core/hasTopic".to_string(), - ))), + )), object: VarOrNodeOrLiteral::Node(NamedNode(Full( "https://ontology.okp4.space/thesaurus/topic/Test".to_string(), ))), @@ -823,20 +829,16 @@ mod tests { namespace: "https://ontology.okp4.space/thesaurus/topic/".to_string(), }, ], - delete: vec![msg::TriplePattern { - subject: VarOrNode::Node(NamedNode(Full(id.to_string()))), - predicate: VarOrNode::Node(NamedNode(Prefixed( - "core:hasTopic".to_string(), - ))), - object: VarOrNodeOrLiteral::Node(NamedNode(Prefixed( + 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![WhereCondition::Simple(TriplePattern(msg::TriplePattern { subject: VarOrNode::Node(NamedNode(Full(id.to_string()))), - predicate: VarOrNode::Node(NamedNode(Prefixed( - "core:hasTopic".to_string(), - ))), + predicate: VarOrNamedNode::NamedNode(Prefixed("core:hasTopic".to_string())), object: VarOrNodeOrLiteral::Node(NamedNode(Prefixed( "thesaurus:Test".to_string(), ))), @@ -858,18 +860,14 @@ mod tests { namespace: "https://ontology.okp4.space/thesaurus/topic/".to_string(), }, ], - delete: vec![msg::TriplePattern { - subject: VarOrNode::Node(NamedNode(Full(id.to_string()))), - predicate: VarOrNode::Node(NamedNode(Prefixed( - "core:hasTopic".to_string(), - ))), - object: VarOrNodeOrLiteral::Variable("o".to_string()), + delete: vec![msg::TripleDeleteTemplate { + subject: VarOrNamedNode::NamedNode(Full(id.to_string())), + predicate: VarOrNamedNode::NamedNode(Prefixed("core:hasTopic".to_string())), + object: VarOrNamedNodeOrLiteral::Variable("o".to_string()), }], r#where: vec![WhereCondition::Simple(TriplePattern(msg::TriplePattern { subject: VarOrNode::Node(NamedNode(Full(id.to_string()))), - predicate: VarOrNode::Node(NamedNode(Prefixed( - "core:hasTopic".to_string(), - ))), + predicate: VarOrNamedNode::NamedNode(Prefixed("core:hasTopic".to_string())), object: VarOrNodeOrLiteral::Variable("o".to_string()), }))], }, @@ -880,14 +878,14 @@ mod tests { ( DeleteData { prefixes: vec![], - delete: vec![msg::TriplePattern { - subject: VarOrNode::Node(NamedNode(Full(id.to_string()))), - predicate: VarOrNode::Variable("p".to_string()), - object: VarOrNodeOrLiteral::Variable("o".to_string()), + delete: vec![msg::TripleDeleteTemplate { + subject: VarOrNamedNode::NamedNode(Full(id.to_string())), + predicate: VarOrNamedNode::Variable("p".to_string()), + object: VarOrNamedNodeOrLiteral::Variable("o".to_string()), }], r#where: vec![WhereCondition::Simple(TriplePattern(msg::TriplePattern { subject: VarOrNode::Node(NamedNode(Full(id.to_string()))), - predicate: VarOrNode::Variable("p".to_string()), + predicate: VarOrNamedNode::Variable("p".to_string()), object: VarOrNodeOrLiteral::Variable("o".to_string()), }))], }, @@ -895,34 +893,34 @@ mod tests { 2, Uint128::from(5272u128), ), - ( - DeleteData { - prefixes: vec![], - delete: vec![], - r#where: vec![WhereCondition::Simple(TriplePattern(msg::TriplePattern { - subject: VarOrNode::Node(NamedNode(Full(id.to_string()))), - predicate: VarOrNode::Variable("p".to_string()), - object: VarOrNodeOrLiteral::Variable("o".to_string()), - }))], - }, - 11, - 2, - Uint128::from(5272u128), - ), - ( - DeleteData { - prefixes: vec![], - delete: vec![], - r#where: vec![WhereCondition::Simple(TriplePattern(msg::TriplePattern { - subject: VarOrNode::Variable("s".to_string()), - predicate: VarOrNode::Variable("p".to_string()), - object: VarOrNodeOrLiteral::Variable("0".to_string()), - }))], - }, - 40, - 17, - Uint128::from(0u128), - ), + // ( + // DeleteData { + // prefixes: vec![], + // delete: vec![], + // r#where: vec![WhereCondition::Simple(TriplePattern(msg::TriplePattern { + // subject: VarOrNode::Node(NamedNode(Full(id.to_string()))), + // predicate: VarOrNamedNode::Variable("p".to_string()), + // object: VarOrNodeOrLiteral::Variable("o".to_string()), + // }))], + // }, + // 11, + // 2, + // Uint128::from(5272u128), + // ), + // ( + // DeleteData { + // prefixes: vec![], + // delete: vec![], + // r#where: vec![WhereCondition::Simple(TriplePattern(msg::TriplePattern { + // subject: VarOrNode::Variable("s".to_string()), + // predicate: VarOrNamedNode::Variable("p".to_string()), + // object: VarOrNodeOrLiteral::Variable("0".to_string()), + // }))], + // }, + // 40, + // 17, + // Uint128::from(0u128), + // ), ]; for case in cases { @@ -992,20 +990,20 @@ mod tests { TC { command: DeleteData { prefixes: vec![], - delete: vec![msg::TriplePattern { - subject: VarOrNode::Node(NamedNode(Prefixed("foo:bar".to_string()))), - predicate: VarOrNode::Node(NamedNode(Full( + delete: vec![msg::TripleDeleteTemplate { + subject: VarOrNamedNode::NamedNode(Prefixed("foo:bar".to_string())), + predicate: VarOrNamedNode::NamedNode(Full( "https://ontology.okp4.space/core/hasTopic".to_string(), - ))), - object: VarOrNodeOrLiteral::Node(NamedNode(Full( + )), + object: VarOrNamedNodeOrLiteral::NamedNode(Full( "https://ontology.okp4.space/thesaurus/topic/Test".to_string(), - ))), + )), }], r#where: vec![WhereCondition::Simple(TriplePattern(msg::TriplePattern { subject: VarOrNode::Node(NamedNode(Prefixed("foo:bar".to_string()))), - predicate: VarOrNode::Node(NamedNode(Full( + predicate: VarOrNamedNode::NamedNode(Full( "https://ontology.okp4.space/core/hasTopic".to_string(), - ))), + )), object: VarOrNodeOrLiteral::Node(NamedNode(Full( "https://ontology.okp4.space/thesaurus/topic/Test".to_string(), ))), @@ -1016,18 +1014,18 @@ mod tests { TC { command: DeleteData { prefixes: vec![], - delete: vec![msg::TriplePattern { - subject: VarOrNode::Node(NamedNode(Full( + delete: vec![msg::TripleDeleteTemplate { + subject: VarOrNamedNode::NamedNode(Full( "https://ontology.okp4.space/thesaurus/topic/Test".to_string(), - ))), - predicate: VarOrNode::Variable("z".to_string()), - object: VarOrNodeOrLiteral::Variable("o".to_string()), + )), + predicate: VarOrNamedNode::Variable("z".to_string()), + object: VarOrNamedNodeOrLiteral::Variable("o".to_string()), }], r#where: vec![WhereCondition::Simple(TriplePattern(msg::TriplePattern { subject: VarOrNode::Node(NamedNode(Full( "https://ontology.okp4.space/thesaurus/topic/Test".to_string(), ))), - predicate: VarOrNode::Variable("p".to_string()), + predicate: VarOrNamedNode::Variable("p".to_string()), object: VarOrNodeOrLiteral::Variable("o".to_string()), }))], }, @@ -1036,16 +1034,16 @@ mod tests { TC { command: DeleteData { prefixes: vec![], - delete: vec![msg::TriplePattern { - subject: VarOrNode::Node(NamedNode(Full( + delete: vec![msg::TripleDeleteTemplate { + subject: VarOrNamedNode::NamedNode(Full( "https://ontology.okp4.space/thesaurus/topic/Test".to_string(), - ))), - predicate: VarOrNode::Node(NamedNode(Full( + )), + predicate: VarOrNamedNode::NamedNode(Full( "https://ontology.okp4.space/core/hasTopic".to_string(), - ))), - object: VarOrNodeOrLiteral::Node(NamedNode(Full( + )), + object: VarOrNamedNodeOrLiteral::NamedNode(Full( "https://ontology.okp4.space/thesaurus/topic/Test".to_string(), - ))), + )), }], r#where: vec![], }, @@ -1161,9 +1159,9 @@ mod tests { r#where: vec![WhereCondition::Simple(TriplePattern( msg::TriplePattern { subject: VarOrNode::Variable("a".to_string()), - predicate: VarOrNode::Node(NamedNode(Full( + predicate: VarOrNamedNode::NamedNode(Full( "https://ontology.okp4.space/core/hasDescription".to_string(), - ))), + )), object: VarOrNodeOrLiteral::Variable("b".to_string()), }, ))], @@ -1252,9 +1250,9 @@ mod tests { r#where: vec![WhereCondition::Simple(TriplePattern( msg::TriplePattern { subject: VarOrNode::Variable("a".to_string()), - predicate: VarOrNode::Node(NamedNode(Prefixed( + predicate: VarOrNamedNode::NamedNode(Prefixed( "core:hasDescription".to_string(), - ))), + )), object: VarOrNodeOrLiteral::Literal(Literal::LanguageTaggedString { value: "A test Dataset.".to_string(), language: "en".to_string() }), }, ))], @@ -1287,7 +1285,7 @@ mod tests { r#where: vec![WhereCondition::Simple(TriplePattern( msg::TriplePattern { subject: VarOrNode::Node(NamedNode(Full("https://ontology.okp4.space/dataverse/dataset/metadata/d1615703-4ee1-4e2f-997e-15aecf1eea4e".to_string()))), - predicate: VarOrNode::Variable("a".to_string()), + predicate: VarOrNamedNode::Variable("a".to_string()), object: VarOrNodeOrLiteral::Literal(Literal::LanguageTaggedString { value: "A test Dataset.".to_string(), language: "en".to_string() }), }, ))], @@ -1355,18 +1353,18 @@ mod tests { WhereCondition::Simple(TriplePattern( msg::TriplePattern { subject: VarOrNode::Variable("a".to_string()), - predicate: VarOrNode::Node(NamedNode(Prefixed( + predicate: VarOrNamedNode::NamedNode(Prefixed( "core:hasTemporalCoverage".to_string(), - ))), + )), object: VarOrNodeOrLiteral::Node(BlankNode("a".to_string())), }, )), WhereCondition::Simple(TriplePattern( msg::TriplePattern { subject: VarOrNode::Node(BlankNode("a".to_string())), - predicate: VarOrNode::Node(NamedNode(Prefixed( + predicate: VarOrNamedNode::NamedNode(Prefixed( "core:hasStartDate".to_string(), - ))), + )), object: VarOrNodeOrLiteral::Variable("b".to_string()), }, ))], @@ -1404,18 +1402,18 @@ mod tests { WhereCondition::Simple(TriplePattern( msg::TriplePattern { subject: VarOrNode::Variable("a".to_string()), - predicate: VarOrNode::Node(NamedNode(Prefixed( + predicate: VarOrNamedNode::NamedNode(Prefixed( "core:hasTemporalCoverage".to_string(), - ))), + )), object: VarOrNodeOrLiteral::Variable("blank".to_string()), }, )), WhereCondition::Simple(TriplePattern( msg::TriplePattern { subject: VarOrNode::Variable("blank".to_string()), - predicate: VarOrNode::Node(NamedNode(Prefixed( + predicate: VarOrNamedNode::NamedNode(Prefixed( "core:hasStartDate".to_string(), - ))), + )), object: VarOrNodeOrLiteral::Variable("b".to_string()), }, ))], @@ -1453,18 +1451,18 @@ mod tests { WhereCondition::Simple(TriplePattern( msg::TriplePattern { subject: VarOrNode::Variable("a".to_string()), - predicate: VarOrNode::Node(NamedNode(Prefixed( + predicate: VarOrNamedNode::NamedNode(Prefixed( "core:hasTemporalCoverage".to_string(), - ))), + )), object: VarOrNodeOrLiteral::Node(BlankNode("blank1".to_string())), }, )), WhereCondition::Simple(TriplePattern( msg::TriplePattern { subject: VarOrNode::Node(BlankNode("blank2".to_string())), - predicate: VarOrNode::Node(NamedNode(Prefixed( + predicate: VarOrNamedNode::NamedNode(Prefixed( "core:hasInformation".to_string(), - ))), + )), object: VarOrNodeOrLiteral::Variable("b".to_string()), }, ))], @@ -1502,9 +1500,9 @@ mod tests { WhereCondition::Simple(TriplePattern( msg::TriplePattern { subject: VarOrNode::Variable("a".to_string()), - predicate: VarOrNode::Node(NamedNode(Prefixed( + predicate: VarOrNamedNode::NamedNode(Prefixed( "core:hasTemporalCoverage".to_string(), - ))), + )), object: VarOrNodeOrLiteral::Variable("b".to_string()), }, ))], @@ -1524,7 +1522,7 @@ mod tests { ( "b".to_string(), Value::BlankNode { - value: "riog00000001".to_string(), + value: "b0".to_string(), } ) ]) @@ -1600,9 +1598,9 @@ mod tests { select: vec![SelectItem::Variable("a".to_string())], r#where: vec![WhereCondition::Simple(TriplePattern(msg::TriplePattern { subject: VarOrNode::Variable("a".to_string()), - predicate: VarOrNode::Node(NamedNode(Prefixed( + predicate: VarOrNamedNode::NamedNode(Prefixed( "invalid:hasDescription".to_string(), - ))), + )), object: VarOrNodeOrLiteral::Literal(Literal::LanguageTaggedString { value: "A test Dataset.".to_string(), language: "en".to_string(), @@ -1618,9 +1616,9 @@ mod tests { select: vec![SelectItem::Variable("u".to_string())], r#where: vec![WhereCondition::Simple(TriplePattern(msg::TriplePattern { subject: VarOrNode::Variable("a".to_string()), - predicate: VarOrNode::Node(NamedNode(Full( + predicate: VarOrNamedNode::NamedNode(Full( "https://ontology.okp4.space/core/hasDescription".to_string(), - ))), + )), object: VarOrNodeOrLiteral::Literal(Literal::LanguageTaggedString { value: "A test Dataset.".to_string(), language: "en".to_string(), @@ -1730,9 +1728,9 @@ mod tests { r#where: vec![WhereCondition::Simple(TriplePattern( msg::TriplePattern { subject: VarOrNode::Variable("a".to_string()), - predicate: VarOrNode::Node(NamedNode(Full( + predicate: VarOrNamedNode::NamedNode(Full( "https://ontology.okp4.space/core/hasDescription".to_string(), - ))), + )), object: VarOrNodeOrLiteral::Variable("b".to_string()), }, ))], @@ -1904,9 +1902,9 @@ mod tests { r#where: vec![WhereCondition::Simple(TriplePattern( msg::TriplePattern { subject: VarOrNode::Variable("a".to_string()), - predicate: VarOrNode::Node(NamedNode(Prefixed( + predicate: VarOrNamedNode::NamedNode(Prefixed( "core:hasDescription".to_string(), - ))), + )), object: VarOrNodeOrLiteral::Literal(Literal::LanguageTaggedString { value: "A test Dataset.".to_string(), language: "en".to_string() }), }, ))], @@ -1969,9 +1967,9 @@ mod tests { r#where: vec![WhereCondition::Simple(TriplePattern( msg::TriplePattern { subject: VarOrNode::Variable("a".to_string()), - predicate: VarOrNode::Node(NamedNode(Prefixed( + predicate: VarOrNamedNode::NamedNode(Prefixed( "core:hasPublisher".to_string(), - ))), + )), object: VarOrNodeOrLiteral::Literal(Literal::Simple("OKP4".to_string())), }, ))], @@ -2037,9 +2035,9 @@ mod tests { r#where: vec![WhereCondition::Simple(TriplePattern( msg::TriplePattern { subject: VarOrNode::Node(NamedNode(Prefixed("metadata-dataset:80b1f84e-86dc-4730-b54f-701ad9b1888a".to_string()))), - predicate: VarOrNode::Node(NamedNode(Prefixed( + predicate: VarOrNamedNode::NamedNode(Prefixed( "core:hasTemporalCoverage".to_string(), - ))), + )), object: VarOrNodeOrLiteral::Variable("x".to_string()), }, )), @@ -2050,7 +2048,7 @@ mod tests { DescribeResponse { format: DataFormat::Turtle, data: Binary::from( - " , ;\n\t \"2022-01-01T00:00:00+00:00\"^^ .\n".to_string().as_bytes().to_vec()), + " , ;\n\t \"2022-01-01T00:00:00+00:00\"^^ .\n".to_string().as_bytes().to_vec()), } ), ]; @@ -2095,27 +2093,28 @@ mod tests { #[test] fn proper_construct() { let id = "https://ontology.okp4.space/dataverse/dataspace/metadata/dcf48417-01c5-4b43-9bc7-49e54c028473"; - let cases = vec![( - QueryMsg::Construct { - query: ConstructQuery { - prefixes: vec![], - construct: vec![], - r#where: vec![WhereCondition::Simple(TriplePattern(msg::TriplePattern { - subject: VarOrNode::Node(NamedNode(Full(id.to_string()))), - predicate: VarOrNode::Node(NamedNode(Full( - "https://ontology.okp4.space/core/hasTag".to_string(), - ))), - object: VarOrNodeOrLiteral::Variable("o".to_string()), - }))], - }, - format: None, - }, - ConstructResponse { - format: DataFormat::Turtle, - data: Binary::from( - " \"Test\" , \"OKP4\" .\n".to_string().as_bytes().to_vec()), - }, - ), + let cases = vec![ + // ( + // QueryMsg::Construct { + // query: ConstructQuery { + // prefixes: vec![], + // construct: vec![], + // r#where: vec![WhereCondition::Simple(TriplePattern(msg::TriplePattern { + // subject: VarOrNode::Node(NamedNode(Full(id.to_string()))), + // predicate: VarOrNamedNode::NamedNode(Full( + // "https://ontology.okp4.space/core/hasTag".to_string(), + // )), + // object: VarOrNodeOrLiteral::Variable("o".to_string()), + // }))], + // }, + // format: None, + // }, + // ConstructResponse { + // format: DataFormat::Turtle, + // data: Binary::from( + // " \"Test\" , \"OKP4\" .\n".to_string().as_bytes().to_vec()), + // }, + // ), ( QueryMsg::Construct { query: ConstructQuery { @@ -2124,19 +2123,19 @@ mod tests { Prefix { prefix: "metadata-dataset".to_string(), namespace: "https://ontology.okp4.space/dataverse/dataset/metadata/".to_string() }, ], construct: vec![ - msg::TriplePattern { + msg::TripleConstructTemplate { subject: VarOrNode::Node(NamedNode(Prefixed("my-ns:instance-1".to_string()))), - predicate: VarOrNode::Node(NamedNode(Full( + predicate: VarOrNamedNode::NamedNode(Full( "https://my-ns/predicate/tag".to_string(), - ))), + )), object: VarOrNodeOrLiteral::Variable("o".to_string()), } ], r#where: vec![WhereCondition::Simple(TriplePattern(msg::TriplePattern { subject: VarOrNode::Node(NamedNode(Full(id.to_string()))), - predicate: VarOrNode::Node(NamedNode(Full( + predicate: VarOrNamedNode::NamedNode(Full( "https://ontology.okp4.space/core/hasTag".to_string(), - ))), + )), object: VarOrNodeOrLiteral::Variable("o".to_string()), }))], }, diff --git a/contracts/okp4-cognitarium/src/msg.rs b/contracts/okp4-cognitarium/src/msg.rs index 52b6bd25..c0b5a87c 100644 --- a/contracts/okp4-cognitarium/src/msg.rs +++ b/contracts/okp4-cognitarium/src/msg.rs @@ -434,8 +434,7 @@ pub struct ConstructQuery { /// The prefixes used in the query. pub prefixes: Vec, /// The triples to construct. - /// If nothing is provided, the patterns from the `where` clause are used for construction. - pub construct: Vec, + pub construct: Vec, /// The WHERE clause. /// This clause is used to specify the triples to construct using variable bindings. pub r#where: WhereClause, @@ -489,7 +488,10 @@ pub trait HasVariables { /// Returns the set of variables used in a triple pattern or template as [SelectItem]. fn as_select_item(&self) -> Vec { - self.variables().iter().map(SelectItem::Variable).collect() + self.variables() + .into_iter() + .map(SelectItem::Variable) + .collect() } } @@ -517,7 +519,33 @@ pub struct TripleDeleteTemplate { impl HasVariables for TripleDeleteTemplate { fn variables(&self) -> Vec { - var_util::merge_variables(&[&self.subject, &self.predicate, &self.object]) + var_util::merge_variables(&[ + self.subject.variable(), + self.predicate.variable(), + self.object.variable(), + ]) + } +} + +/// # TripleConstructTemplate +/// Represents a triple template to be forged for a construct query. +#[cw_serde] +pub struct TripleConstructTemplate { + /// The subject of the triple pattern. + pub subject: VarOrNode, + /// The predicate of the triple pattern. + pub predicate: VarOrNamedNode, + /// The object of the triple pattern. + pub object: VarOrNodeOrLiteral, +} + +impl HasVariables for TripleConstructTemplate { + fn variables(&self) -> Vec { + var_util::merge_variables(&[ + self.subject.variable(), + self.predicate.variable(), + self.object.variable(), + ]) } } @@ -535,7 +563,11 @@ pub struct TriplePattern { impl HasVariables for TriplePattern { fn variables(&self) -> Vec { - var_util::merge_variables(&[&self.subject, &self.predicate, &self.object]) + var_util::merge_variables(&[ + self.subject.variable(), + self.predicate.variable(), + self.object.variable(), + ]) } } @@ -544,16 +576,16 @@ trait MaybeVariable { } mod var_util { - use crate::msg::MaybeVariable; use std::collections::HashSet; - pub fn merge_variables(maybe_vars: &[impl MaybeVariable]) -> Vec { + pub fn merge_variables(maybe_vars: &[Option<&str>]) -> Vec { maybe_vars .iter() - .map(MaybeVariable::variable) + .copied() .filter_map(|maybe_var| maybe_var) .collect::>() .into_iter() + .map(str::to_string) .collect() } } @@ -689,6 +721,7 @@ pub enum Node { #[cfg(test)] mod tests { + use super::*; use crate::msg::Literal::Simple; use crate::msg::Node::{BlankNode, NamedNode}; use crate::msg::IRI::{Full, Prefixed}; @@ -744,7 +777,7 @@ mod tests { ( TriplePattern { subject: VarOrNode::Variable(s.clone()), - predicate: VarOrNode::Variable(p.clone()), + predicate: VarOrNamedNode::Variable(p.clone()), object: VarOrNodeOrLiteral::Variable(o.clone()), }, vec![s.clone(), p.clone(), o.clone()], @@ -752,7 +785,7 @@ mod tests { ( TriplePattern { subject: VarOrNode::Node(NamedNode(Full(node.clone()))), - predicate: VarOrNode::Variable(p.clone()), + predicate: VarOrNamedNode::Variable(p.clone()), object: VarOrNodeOrLiteral::Variable(o.clone()), }, vec![p.clone(), o.clone()], @@ -760,7 +793,7 @@ mod tests { ( TriplePattern { subject: VarOrNode::Node(NamedNode(Prefixed(prefixed.clone()))), - predicate: VarOrNode::Variable(p.clone()), + predicate: VarOrNamedNode::Variable(p.clone()), object: VarOrNodeOrLiteral::Variable(o.clone()), }, vec![p.clone(), o.clone()], @@ -768,7 +801,7 @@ mod tests { ( TriplePattern { subject: VarOrNode::Node(BlankNode(node.clone())), - predicate: VarOrNode::Variable(p.clone()), + predicate: VarOrNamedNode::Variable(p.clone()), object: VarOrNodeOrLiteral::Variable(o.clone()), }, vec![p.clone(), o.clone()], @@ -776,7 +809,7 @@ mod tests { ( TriplePattern { subject: VarOrNode::Variable(s.clone()), - predicate: VarOrNode::Node(NamedNode(Full(node.clone()))), + predicate: VarOrNamedNode::NamedNode(Full(node.clone())), object: VarOrNodeOrLiteral::Variable(o.clone()), }, vec![s.clone(), o], @@ -784,7 +817,7 @@ mod tests { ( TriplePattern { subject: VarOrNode::Variable(s.clone()), - predicate: VarOrNode::Variable(p.clone()), + predicate: VarOrNamedNode::Variable(p.clone()), object: VarOrNodeOrLiteral::Literal(Simple(literal.clone())), }, vec![s, p], @@ -792,7 +825,7 @@ mod tests { ( TriplePattern { subject: VarOrNode::Node(BlankNode(node)), - predicate: VarOrNode::Node(NamedNode(Prefixed(prefixed))), + predicate: VarOrNamedNode::NamedNode(Prefixed(prefixed)), object: VarOrNodeOrLiteral::Literal(Simple(literal)), }, vec![], diff --git a/contracts/okp4-cognitarium/src/querier/engine.rs b/contracts/okp4-cognitarium/src/querier/engine.rs index 0414b8de..03b95767 100644 --- a/contracts/okp4-cognitarium/src/querier/engine.rs +++ b/contracts/okp4-cognitarium/src/querier/engine.rs @@ -1,6 +1,5 @@ use crate::msg::{ - SelectItem, TriplePattern, VarOrNamedNode, VarOrNamedNodeOrLiteral, VarOrNode, - VarOrNodeOrLiteral, + SelectItem, VarOrNamedNode, VarOrNamedNodeOrLiteral, VarOrNode, VarOrNodeOrLiteral, }; use crate::querier::mapper::{iri_as_node, literal_as_object}; use crate::querier::plan::{PatternValue, QueryNode, QueryPlan}; @@ -457,13 +456,13 @@ impl<'a> SolutionsIterator<'a> { self, storage: &dyn Storage, prefixes: &HashMap, - patterns: Vec, + templates: Vec<(VarOrNode, VarOrNamedNode, VarOrNodeOrLiteral)>, ns_cache: Vec, ) -> StdResult> { let mut ns_resolver = ns_cache.into(); let atoms_iter = - ResolvedAtomIterator::try_new(&mut ns_resolver, storage, self, prefixes, patterns)?; + ResolvedAtomIterator::try_new(&mut ns_resolver, storage, self, prefixes, templates)?; atoms_iter.collect() } } @@ -699,16 +698,16 @@ impl<'a> ResolvedAtomIterator<'a> { storage: &'a dyn Storage, solutions: SolutionsIterator<'a>, prefixes: &HashMap, - patterns: Vec, + templates: Vec<(VarOrNode, VarOrNamedNode, VarOrNodeOrLiteral)>, ) -> StdResult { Ok(Self { ns_resolver, id_issuer: IdentifierIssuer::new("b", 0u128), storage, iter: solutions, - templates: patterns - .iter() - .map(|p| AtomTemplate::try_new(prefixes, p)) + templates: templates + .into_iter() + .map(|t| AtomTemplate::try_new(prefixes, t)) .collect::>>()?, buffer: VecDeque::new(), }) @@ -758,18 +757,18 @@ struct AtomTemplate { impl AtomTemplate { pub fn try_new( prefixes: &HashMap, - pattern: &TriplePattern, + (s_tpl, p_tpl, o_tpl): (VarOrNode, VarOrNamedNode, VarOrNodeOrLiteral), ) -> StdResult { Ok(Self { - subject: match &pattern.subject { + subject: match s_tpl { VarOrNode::Variable(key) => Right(key.clone()), VarOrNode::Node(n) => Left((n.clone(), prefixes).try_into()?), }, - property: match &pattern.predicate { - VarOrNode::Variable(key) => Right(key.clone()), - VarOrNode::Node(n) => Left((n.clone(), prefixes).try_into()?), + property: match p_tpl { + VarOrNamedNode::Variable(key) => Right(key), + VarOrNamedNode::NamedNode(iri) => Left((iri, prefixes).try_into()?), }, - value: match &pattern.object { + value: match o_tpl { VarOrNodeOrLiteral::Variable(key) => Right(key.clone()), VarOrNodeOrLiteral::Node(n) => Left((n.clone(), prefixes).try_into()?), VarOrNodeOrLiteral::Literal(l) => Left((l.clone(), prefixes).try_into()?), diff --git a/contracts/okp4-cognitarium/src/rdf/mapper.rs b/contracts/okp4-cognitarium/src/rdf/mapper.rs index 968bf1c2..95977462 100644 --- a/contracts/okp4-cognitarium/src/rdf/mapper.rs +++ b/contracts/okp4-cognitarium/src/rdf/mapper.rs @@ -20,20 +20,15 @@ impl TryFrom<(msg::Node, &HashMap)> for Subject { } } -impl TryFrom<(msg::Node, &HashMap)> for Property { +impl TryFrom<(msg::IRI, &HashMap)> for Property { type Error = StdError; fn try_from( - (node, prefixes): (msg::Node, &HashMap), + (iri, prefixes): (msg::IRI, &HashMap), ) -> Result { - match node { - msg::Node::NamedNode(msg::IRI::Full(uri)) => Ok(Property(uri)), - msg::Node::NamedNode(msg::IRI::Prefixed(curie)) => { - Ok(Property(expand_uri(&curie, prefixes)?)) - } - _ => Err(StdError::generic_err(format!( - "Unsupported predicate node: {node:?}. Expected URI" - ))), + match iri { + msg::IRI::Full(uri) => Ok(Property(uri)), + msg::IRI::Prefixed(curie) => Ok(Property(expand_uri(&curie, prefixes)?)), } } }