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 { match attribute {
&PatternNonValuePlace::Ident(ref kw) => &PatternNonValuePlace::Ident(ref kw) =>
schema.attribute_for_ident(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)), .and_then(|attribute| self.table_for_attribute_and_value(attribute, value)),
&PatternNonValuePlace::Entid(id) => &PatternNonValuePlace::Entid(id) =>
schema.attribute_for_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)), .and_then(|attribute| self.table_for_attribute_and_value(attribute, value)),
// TODO: In a prepared context, defer this decision until a second algebrizing phase. // TODO: In a prepared context, defer this decision until a second algebrizing phase.
// #278. // #278.
@ -974,6 +974,10 @@ impl ConjoiningClauses {
validate_or_join(&o) validate_or_join(&o)
// TODO: apply. // TODO: apply.
}, },
WhereClause::NotJoin(n) => {
validate_not_join(&n)
// TODO: apply.
},
_ => unimplemented!(), _ => unimplemented!(),
} }
} }

View file

@ -46,6 +46,12 @@ error_chain! {
description("non-matching variables in 'or' clause") description("non-matching variables in 'or' clause")
display("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::{ use mentat_query::{
ContainsVariables, ContainsVariables,
OrJoin, OrJoin,
NotJoin,
Variable, Variable,
WhereClause, WhereClause,
UnifyVars, 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)] #[cfg(test)]
mod tests { mod tests {
extern crate mentat_core; extern crate mentat_core;
@ -93,6 +125,7 @@ mod tests {
UnifyVars, UnifyVars,
Variable, Variable,
WhereClause, WhereClause,
WhereNotClause,
}; };
use self::mentat_query_parser::parse_find_string; use self::mentat_query_parser::parse_find_string;

View file

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