WIP - copy what we did for OR & OR Join
This commit is contained in:
parent
8e6f37e709
commit
7c3f6f3698
4 changed files with 82 additions and 4 deletions
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ¬_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;
|
||||
|
|
|
@ -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,24 @@ 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,
|
||||
NotJoin(NotJoin),
|
||||
OrJoin(OrJoin),
|
||||
Pred(Predicate),
|
||||
WhereFn,
|
||||
|
@ -557,7 +571,7 @@ impl ContainsVariables for WhereClause {
|
|||
&Pred(ref p) => p.accumulate_mentioned_variables(acc),
|
||||
&Pattern(ref p) => p.accumulate_mentioned_variables(acc),
|
||||
&Not => (),
|
||||
&NotJoin => (),
|
||||
&NotJoin(ref n) => n.accumulate_mentioned_variables(acc),
|
||||
&WhereFn => (),
|
||||
&RuleExpr => (),
|
||||
}
|
||||
|
@ -570,6 +584,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 clause) => clause.accumulate_mentioned_variables(acc),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -582,6 +597,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 clause) => 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 {
|
||||
|
|
Loading…
Reference in a new issue