Skip to content

Commit

Permalink
fix(cognitarium): avoir error on not found ns at plan building
Browse files Browse the repository at this point in the history
  • Loading branch information
amimart committed Feb 18, 2024
1 parent ed75190 commit 18fe57b
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 8 deletions.
1 change: 1 addition & 0 deletions contracts/okp4-cognitarium/src/querier/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ impl<'a> QueryEngine<'a> {
object.clone(),
))
}),
QueryNode::Noop { .. } => Rc::new(|_| Box::new(iter::empty())),

Check warning on line 80 in contracts/okp4-cognitarium/src/querier/engine.rs

View check run for this annotation

Codecov / codecov/patch

contracts/okp4-cognitarium/src/querier/engine.rs#L80

Added line #L80 was not covered by tests
QueryNode::CartesianProductJoin { left, right } => {
let left = self.eval_node(*left);
let right = self.eval_node(*right);
Expand Down
8 changes: 8 additions & 0 deletions contracts/okp4-cognitarium/src/querier/plan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ pub enum QueryNode {
object: PatternValue<Object>,
},

/// Results in no solutions, this special node is used when we know before plan execution that a node
/// will end up with no possible solutions. For example, using a triple pattern filtering with a constant
/// named node containing a non-existing namespace.
Noop { bound_variables: Vec<usize> },

/// Join two nodes by applying the cartesian product of the nodes variables.
///
/// This should be used when the nodes doesn't have variables in common, and can be seen as a
Expand Down Expand Up @@ -77,6 +82,9 @@ impl QueryNode {
predicate.lookup_bound_variable(callback);
object.lookup_bound_variable(callback);
}
QueryNode::Noop { bound_variables } => {
bound_variables.iter().for_each(|v| callback(*v));
}

Check warning on line 87 in contracts/okp4-cognitarium/src/querier/plan.rs

View check run for this annotation

Codecov / codecov/patch

contracts/okp4-cognitarium/src/querier/plan.rs#L85-L87

Added lines #L85 - L87 were not covered by tests
QueryNode::CartesianProductJoin { left, right }
| QueryNode::ForLoopJoin { left, right } => {
left.lookup_bound_variables(callback);
Expand Down
60 changes: 52 additions & 8 deletions contracts/okp4-cognitarium/src/querier/plan_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,43 @@ impl<'a> PlanBuilder<'a> {
}

fn build_triple_pattern(&mut self, pattern: &TriplePattern) -> StdResult<QueryNode> {
Ok(QueryNode::TriplePattern {
subject: self.build_subject_pattern(pattern.subject.clone())?,
predicate: self.build_predicate_pattern(pattern.predicate.clone())?,
object: self.build_object_pattern(pattern.object.clone())?,
let subject_res = self.build_subject_pattern(pattern.subject.clone());
let predicate_res = self.build_predicate_pattern(pattern.predicate.clone());
let object_res = self.build_object_pattern(pattern.object.clone());

let mut bound_variables: Vec<usize> = vec![];
let maybe_subject = match subject_res {
Ok(value) => {
value.lookup_bound_variable(&mut |v| bound_variables.push(v));
Some(value)
}
Err(err) if NamespaceResolver::is_ns_not_found_error(&err) => None,
_ => Some(subject_res?),
};
let maybe_predicate = match predicate_res {
Ok(value) => {
value.lookup_bound_variable(&mut |v| bound_variables.push(v));
Some(value)
}
Err(err) if NamespaceResolver::is_ns_not_found_error(&err) => None,
_ => Some(predicate_res?),
};
let maybe_object = match object_res {
Ok(value) => {
value.lookup_bound_variable(&mut |v| bound_variables.push(v));
Some(value)
}
Err(err) if NamespaceResolver::is_ns_not_found_error(&err) => None,
_ => Some(object_res?),

Check warning on line 135 in contracts/okp4-cognitarium/src/querier/plan_builder.rs

View check run for this annotation

Codecov / codecov/patch

contracts/okp4-cognitarium/src/querier/plan_builder.rs#L135

Added line #L135 was not covered by tests
};

Ok(match (maybe_subject, maybe_predicate, maybe_object) {
(Some(subject), Some(predicate), Some(object)) => QueryNode::TriplePattern {
subject,
predicate,
object,
},
_ => QueryNode::Noop { bound_variables },
})
}

Expand Down Expand Up @@ -376,7 +409,9 @@ mod test {
predicate: VarOrNode::Variable("p".to_string()),
object: VarOrNodeOrLiteral::Variable("o".to_string()),
},
Err(StdError::not_found("Namespace")),
Ok(QueryNode::Noop {
bound_variables: vec![1usize, 2usize],
}),
),
(
TriplePattern {
Expand All @@ -386,7 +421,9 @@ mod test {
))),
object: VarOrNodeOrLiteral::Variable("o".to_string()),
},
Err(StdError::not_found("Namespace")),
Ok(QueryNode::Noop {
bound_variables: vec![0usize, 2usize],
}),
),
(
TriplePattern {
Expand All @@ -396,7 +433,9 @@ mod test {
"notexisting#outch".to_string(),
))),
},
Err(StdError::not_found("Namespace")),
Ok(QueryNode::Noop {
bound_variables: vec![0usize, 1usize],
}),
),
];

Expand Down Expand Up @@ -451,7 +490,12 @@ mod test {
predicate: VarOrNode::Variable("predicate".to_string()),
object: VarOrNodeOrLiteral::Variable("object".to_string()),
}],
Err(StdError::not_found("Namespace")),
Ok(QueryPlan {
entrypoint: QueryNode::Noop {
bound_variables: vec![0usize, 1usize],
},
variables: vec!["predicate".to_string(), "object".to_string()],
}),
),
(
None,
Expand Down
4 changes: 4 additions & 0 deletions contracts/okp4-cognitarium/src/state/namespaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ impl NamespaceResolver {
None => Err(StdError::not_found("Namespace")),
}
}

pub fn is_ns_not_found_error(err: &StdError) -> bool {
matches!(err, StdError::NotFound { kind, .. } if kind == "Namespace")
}
}

impl Default for NamespaceResolver {
Expand Down

0 comments on commit 18fe57b

Please sign in to comment.