Compare commits

...

2 commits

Author SHA1 Message Date
Emily Toop
24a6cce418 WIP - add ability to have OR's in NOT's and NOT's in OR's 2017-03-31 10:57:39 +01:00
Emily Toop
7c3f6f3698 WIP - copy what we did for OR & OR Join 2017-03-31 10:35:40 +01:00
4 changed files with 86 additions and 6 deletions

View file

@ -498,11 +498,11 @@ impl ConjoiningClauses {
match attribute {
&PatternNonValuePlace::Ident(ref kw) =>
schema.attribute_for_ident(kw)
.when_not(|| self.mark_known_empty(EmptyBecause::InvalidAttributeIdent(kw.clone())))
.(|| self.mark_known_empty(EmptyBecause::InvalidAttributeIdent(kw.clone())))
.and_then(|attribute| self.table_for_attribute_and_value(attribute, value)),
&PatternNonValuePlace::Entid(id) =>
schema.attribute_for_entid(id)
.when_not(|| self.mark_known_empty(EmptyBecause::InvalidAttributeEntid(id)))
.(|| self.mark_known_empty(EmptyBecause::InvalidAttributeEntid(id)))
.and_then(|attribute| self.table_for_attribute_and_value(attribute, value)),
// TODO: In a prepared context, defer this decision until a second algebrizing phase.
// #278.
@ -974,6 +974,10 @@ impl ConjoiningClauses {
validate_or_join(&o)
// TODO: apply.
},
WhereClause::NotJoin(n) => {
validate_not_join(&n)
// TODO: apply.
},
_ => unimplemented!(),
}
}

View file

@ -46,6 +46,12 @@ error_chain! {
description("non-matching variables in 'or' clause")
display("non-matching variables in 'or' clause")
}
NonMatchingVariablesInNotClause {
// TODO: flesh out.
description("non-matching variables in 'not' clause")
display("non-matching variables in 'not' clause")
}
}
}

View file

@ -13,6 +13,7 @@ use std::collections::BTreeSet;
use mentat_query::{
ContainsVariables,
OrJoin,
NotJoin,
Variable,
WhereClause,
UnifyVars,
@ -75,6 +76,37 @@ pub fn validate_or_join(or_join: &OrJoin) -> Result<()> {
}
}
pub fn validate_not_join(no_join: &NotJoin) -> Result<()> {
// Grab our mentioned variables and ensure that the rules are followed.
match not_join.unify_vars {
UnifyVars::Implicit => {
// Each 'leg' must have the same variable set.
if not_join.clauses.len() < 2 {
Ok(())
} else {
let mut clauses = not_join.clauses.iter();
let template = clauses.next().unwrap().collect_mentioned_variables();
for clause in clauses {
if template != clause.collect_mentioned_variables() {
bail!(ErrorKind::NonMatchingVariablesInOrClause);
}
}
Ok(())
}
},
UnifyVars::Explicit(ref vars) => {
// Each leg must use the joined vars.
let var_set: BTreeSet<Variable> = vars.iter().cloned().collect();
for clause in &not_join.clauses {
if !var_set.is_subset(&clause.collect_mentioned_variables()) {
bail!(ErrorKind::NonMatchingVariablesInOrClause);
}
}
Ok(())
},
}
}
#[cfg(test)]
mod tests {
extern crate mentat_core;
@ -93,6 +125,7 @@ mod tests {
UnifyVars,
Variable,
WhereClause,
WhereNotClause,
};
use self::mentat_query_parser::parse_find_string;

View file

@ -508,6 +508,7 @@ pub enum UnifyVars {
pub enum OrWhereClause {
Clause(WhereClause),
And(Vec<WhereClause>),
Not(Vec<WhereNotClause>),
}
#[derive(Clone, Debug, Eq, PartialEq)]
@ -516,11 +517,25 @@ pub struct OrJoin {
pub clauses: Vec<OrWhereClause>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum WhereNotClause {
Clause(WhereClause),
And(Vec<WhereClause>),
Or(Vec<OrWhereClause>),
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct NotJoin {
pub unify_vars: UnifyVars,
pub clauses: Vec<WhereNotClause>,
}
#[allow(dead_code)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum WhereClause {
Not,
NotJoin,
Not(Box<WhereNotClause>),
NotJoin(NotJoin),
Or(Box<OrWhereClause>),
OrJoin(OrJoin),
Pred(Predicate),
WhereFn,
@ -553,11 +568,12 @@ impl ContainsVariables for WhereClause {
fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
use WhereClause::*;
match self {
&Or(ref o) => o.accumulate_mentioned_variables(acc),
&OrJoin(ref o) => o.accumulate_mentioned_variables(acc),
&Pred(ref p) => p.accumulate_mentioned_variables(acc),
&Pattern(ref p) => p.accumulate_mentioned_variables(acc),
&Not => (),
&NotJoin => (),
&Not(ref n) => n.accumulate_mentioned_variables(acc),
&NotJoin(ref n) => n.accumulate_mentioned_variables(acc),
&WhereFn => (),
&RuleExpr => (),
}
@ -570,6 +586,7 @@ impl ContainsVariables for OrWhereClause {
match self {
&And(ref clauses) => for clause in clauses { clause.accumulate_mentioned_variables(acc) },
&Clause(ref clause) => clause.accumulate_mentioned_variables(acc),
&Not(ref clauses) => for clause in clauses { clause.accumulate_mentioned_variables(acc) },
}
}
}
@ -582,6 +599,26 @@ impl ContainsVariables for OrJoin {
}
}
impl ContainsVariables for WhereNotClause {
fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
use WhereNotClause::*;
match self {
&And(ref clauses) => for clause in clauses { clause.accumulate_mentioned_variables(acc) },
&Clause(ref clause) => clause.accumulate_mentioned_variables(acc),
&Or(ref clauses) => for clause in clauses { clause.accumulate_mentioned_variables(acc) },
}
}
}
impl ContainsVariables for NotJoin {
fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
for clause in &self.clauses {
clause.accumulate_mentioned_variables(acc);
}
}
}
impl ContainsVariables for Predicate {
fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
for arg in &self.args {