Skip to content

Commit

Permalink
feat(cognitarium)!: rework delete input to remove template bnodes
Browse files Browse the repository at this point in the history
  • Loading branch information
amimart committed Feb 28, 2024
1 parent 93acb93 commit 7dfb48e
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 96 deletions.
58 changes: 20 additions & 38 deletions contracts/okp4-cognitarium/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ pub fn execute(

pub mod execute {
use super::*;
use crate::msg::{DataFormat, Prefix, TriplePattern, WhereClause};
use crate::msg::{
DataFormat, HasVariables, Prefix, TripleDeleteTemplate, TriplePattern, WhereClause,
};
use crate::querier::{PlanBuilder, QueryEngine};
use crate::rdf::PrefixMap;
use crate::state::HasCachedNamespaces;
Expand Down Expand Up @@ -88,28 +90,31 @@ pub mod execute {
deps: DepsMut<'_>,
info: MessageInfo,
prefixes: Vec<Prefix>,
delete: Vec<TriplePattern>,
delete: Vec<TripleDeleteTemplate>,
r#where: WhereClause,
) -> Result<Response, ContractError> {
verify_owner(&deps, &info)?;

let patterns: Vec<TriplePattern> = if delete.is_empty() {
util::as_triple_patterns(&r#where)?
} else {
delete
};
if delete.is_empty() {
return Ok(Response::new()
.add_attribute("action", "delete")
.add_attribute("triple_count", 0));
}

let prefix_map = <PrefixMap>::from(prefixes).into_inner();
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)
.select(plan, util::as_select_variables(&patterns))?
.select(plan, delete.as_select_item())?
.solutions
.resolve_triples(
deps.storage,
&prefix_map,
patterns,
delete
.into_iter()
.map(|t| (t.subject, t.predicate, t.object))
.collect(),
plan_builder.cached_namespaces(),
)?;

Expand Down Expand Up @@ -141,9 +146,9 @@ pub fn query(deps: Deps<'_>, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
pub mod query {
use super::*;
use crate::msg::{
ConstructQuery, ConstructResponse, DescribeQuery, DescribeResponse, Node, SelectQuery,
SelectResponse, SimpleWhereCondition, StoreResponse, TriplePattern, VarOrNamedNode,
VarOrNode, VarOrNodeOrLiteral, WhereCondition,
ConstructQuery, ConstructResponse, DescribeQuery, DescribeResponse, HasVariables, Node,
SelectQuery, SelectResponse, SimpleWhereCondition, StoreResponse, TriplePattern,
VarOrNamedNode, VarOrNode, VarOrNodeOrLiteral, WhereCondition,
};
use crate::querier::{PlanBuilder, QueryEngine};
use crate::rdf::PrefixMap;
Expand Down Expand Up @@ -277,7 +282,7 @@ pub mod query {
let plan = plan_builder.build_plan(&r#where)?;

let atoms = QueryEngine::new(deps.storage)
.select(plan, util::as_select_variables(&patterns))
.select(plan, patterns.as_select_item())
.and_then(|res| {
res.solutions.resolve_atoms(
deps.storage,
Expand Down Expand Up @@ -313,34 +318,11 @@ pub mod query {

pub mod util {
use super::*;
use crate::msg::{
Head, Results, SelectItem, SelectResponse, SimpleWhereCondition, TriplePattern, Value,
WhereCondition,
};
use crate::msg::{Head, Results, SelectResponse, Value};
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<SelectItem> {
let variables = patterns
.iter()
.flat_map(TriplePattern::variables)
.collect::<HashSet<_>>()
.into_iter()
.map(SelectItem::Variable)
.collect();
variables
}

pub fn as_triple_patterns(r#where: &[WhereCondition]) -> StdResult<Vec<TriplePattern>> {
r#where
.iter()
.map(|c| match c {
WhereCondition::Simple(SimpleWhereCondition::TriplePattern(tp)) => Ok(tp.clone()),
})
.collect::<StdResult<_>>()
}
use std::collections::BTreeMap;

pub fn map_select_solutions(
deps: Deps<'_>,
Expand Down
134 changes: 114 additions & 20 deletions contracts/okp4-cognitarium/src/msg.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use cosmwasm_schema::{cw_serde, QueryResponses};
use cosmwasm_std::{Binary, Uint128};
use derive_builder::Builder;
use std::collections::BTreeMap;
use std::collections::{BTreeMap, HashSet};

/// Instantiate message
#[cw_serde]
Expand Down Expand Up @@ -67,9 +67,8 @@ pub enum ExecuteMsg {
DeleteData {
/// The prefixes used in the operation.
prefixes: Vec<Prefix>,
/// Specifies the specific triple patterns to delete.
/// If nothing is provided, the patterns from the `where` clause are used for deletion.
delete: Vec<TriplePattern>,
/// Specifies the specific triple templates to delete.
delete: Vec<TripleDeleteTemplate>,
/// Defines the patterns that data (RDF triples) should match in order for it to be
/// considered for deletion.
r#where: WhereClause,
Expand Down Expand Up @@ -484,6 +483,44 @@ pub enum SimpleWhereCondition {
TriplePattern(TriplePattern),
}

pub trait HasVariables {
/// Returns the set of variables used in a triple pattern or template.
fn variables(&self) -> Vec<String>;

/// Returns the set of variables used in a triple pattern or template as [SelectItem].
fn as_select_item(&self) -> Vec<SelectItem> {
self.variables().iter().map(SelectItem::Variable).collect()
}
}

impl<T: HasVariables> HasVariables for Vec<T> {
fn variables(&self) -> Vec<String> {
self.iter()
.flat_map(|t| t.variables())
.collect::<HashSet<_>>()
.into_iter()
.collect()
}
}

/// # TripleDeleteTemplate
/// Represents a triple template to be deleted.
#[cw_serde]
pub struct TripleDeleteTemplate {
/// The subject of the triple pattern.
pub subject: VarOrNamedNode,
/// The predicate of the triple pattern.
pub predicate: VarOrNamedNode,
/// The object of the triple pattern.
pub object: VarOrNamedNodeOrLiteral,
}

impl HasVariables for TripleDeleteTemplate {
fn variables(&self) -> Vec<String> {
var_util::merge_variables(&[&self.subject, &self.predicate, &self.object])
}
}

/// # TriplePattern
/// Represents a triple pattern in a [SimpleWhereCondition].
#[cw_serde]
Expand All @@ -496,24 +533,28 @@ pub struct TriplePattern {
pub object: VarOrNodeOrLiteral,
}

impl TriplePattern {
/// Returns the variables used in the triple pattern.
pub fn variables(&self) -> Vec<String> {
let mut variables: Vec<String> = vec![];

if let VarOrNode::Variable(var) = &self.subject {
variables.push(var.clone());
}
impl HasVariables for TriplePattern {
fn variables(&self) -> Vec<String> {
var_util::merge_variables(&[&self.subject, &self.predicate, &self.object])
}
}

if let VarOrNode::Variable(var) = &self.predicate {
variables.push(var.clone());
}
trait MaybeVariable {
fn variable(&self) -> Option<&str>;
}

if let VarOrNodeOrLiteral::Variable(var) = &self.object {
variables.push(var.clone());
}
mod var_util {
use crate::msg::MaybeVariable;
use std::collections::HashSet;

variables
pub fn merge_variables(maybe_vars: &[impl MaybeVariable]) -> Vec<String> {
maybe_vars
.iter()
.map(MaybeVariable::variable)
.filter_map(|maybe_var| maybe_var)
.collect::<HashSet<_>>()
.into_iter()
.collect()
}
}

Expand All @@ -529,6 +570,15 @@ pub enum VarOrNode {
Node(Node),
}

impl MaybeVariable for VarOrNode {
fn variable(&self) -> Option<&str> {
match self {
Self::Variable(v) => Some(v.as_str()),
_ => None,
}
}
}

/// # VarOrNamedNode {
/// Represents either a variable or a named node (IRI).
#[cw_serde]
Expand All @@ -541,6 +591,15 @@ pub enum VarOrNamedNode {
NamedNode(IRI),
}

impl MaybeVariable for VarOrNamedNode {
fn variable(&self) -> Option<&str> {
match self {
Self::Variable(v) => Some(v.as_str()),
_ => None,
}
}
}

/// # VarOrNodeOrLiteral
/// Represents either a variable, a node or a literal.
#[cw_serde]
Expand All @@ -557,6 +616,40 @@ pub enum VarOrNodeOrLiteral {
Literal(Literal),
}

impl MaybeVariable for VarOrNodeOrLiteral {
fn variable(&self) -> Option<&str> {
match self {
Self::Variable(v) => Some(v.as_str()),
_ => None,
}
}
}

/// # VarOrNamedNodeOrLiteral
/// Represents either a variable, a named node or a literal.
#[cw_serde]
pub enum VarOrNamedNodeOrLiteral {
/// # Variable
/// A variable.
Variable(String),
/// # NamedNode
/// An RDF [IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-iri).
NamedNode(IRI),
/// # Literal
/// An RDF [literal](https://www.w3.org/TR/rdf11-concepts/#dfn-literal), i.e. a simple literal,
/// a language-tagged string or a typed value.
Literal(Literal),
}

impl MaybeVariable for VarOrNamedNodeOrLiteral {
fn variable(&self) -> Option<&str> {
match self {
Self::Variable(v) => Some(v.as_str()),
_ => None,
}
}
}

/// # Literal
/// An RDF [literal](https://www.w3.org/TR/rdf11-concepts/#dfn-literal).
#[cw_serde]
Expand Down Expand Up @@ -600,7 +693,8 @@ mod tests {
use crate::msg::Node::{BlankNode, NamedNode};
use crate::msg::IRI::{Full, Prefixed};
use crate::msg::{
InstantiateMsg, StoreLimitsInput, TriplePattern, VarOrNode, VarOrNodeOrLiteral,
HasVariables, InstantiateMsg, StoreLimitsInput, TriplePattern, VarOrNode,
VarOrNodeOrLiteral,
};
use cosmwasm_std::Uint128;
use schemars::_serde_json;
Expand Down
Loading

0 comments on commit 7dfb48e

Please sign in to comment.