|
|
@ -1,5 +1,6 @@
|
|
|
|
use std::collections::btree_map::Entry;
|
|
|
|
use std::collections::btree_map::Entry;
|
|
|
|
use std::collections::{BTreeMap, BTreeSet};
|
|
|
|
use std::collections::{BTreeMap, BTreeSet};
|
|
|
|
|
|
|
|
use std::iter;
|
|
|
|
|
|
|
|
|
|
|
|
use anyhow::Result;
|
|
|
|
use anyhow::Result;
|
|
|
|
use itertools::Itertools;
|
|
|
|
use itertools::Itertools;
|
|
|
@ -33,13 +34,14 @@ impl SessionTx {
|
|
|
|
.map(|o| self.parse_rule_definition(o, default_vld));
|
|
|
|
.map(|o| self.parse_rule_definition(o, default_vld));
|
|
|
|
let mut collected: BTreeMap<Keyword, Vec<Rule>> = BTreeMap::new();
|
|
|
|
let mut collected: BTreeMap<Keyword, Vec<Rule>> = BTreeMap::new();
|
|
|
|
for res in rules {
|
|
|
|
for res in rules {
|
|
|
|
let (name, rule) = res?;
|
|
|
|
for (name, rule) in res? {
|
|
|
|
match collected.entry(name) {
|
|
|
|
match collected.entry(name) {
|
|
|
|
Entry::Vacant(e) => {
|
|
|
|
Entry::Vacant(e) => {
|
|
|
|
e.insert(vec![rule]);
|
|
|
|
e.insert(vec![rule]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Entry::Occupied(mut e) => {
|
|
|
|
Entry::Occupied(mut e) => {
|
|
|
|
e.get_mut().push(rule);
|
|
|
|
e.get_mut().push(rule);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -234,7 +236,7 @@ impl SessionTx {
|
|
|
|
&mut self,
|
|
|
|
&mut self,
|
|
|
|
payload: &JsonValue,
|
|
|
|
payload: &JsonValue,
|
|
|
|
default_vld: Validity,
|
|
|
|
default_vld: Validity,
|
|
|
|
) -> Result<(Keyword, Rule)> {
|
|
|
|
) -> Result<impl Iterator<Item = (Keyword, Rule)>> {
|
|
|
|
let rule_name = payload.get("rule").ok_or_else(|| {
|
|
|
|
let rule_name = payload.get("rule").ok_or_else(|| {
|
|
|
|
QueryCompilationError::UnexpectedForm(
|
|
|
|
QueryCompilationError::UnexpectedForm(
|
|
|
|
payload.clone(),
|
|
|
|
payload.clone(),
|
|
|
@ -307,52 +309,50 @@ impl SessionTx {
|
|
|
|
.into());
|
|
|
|
.into());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Ok((
|
|
|
|
Ok(iter::once((
|
|
|
|
rule_name,
|
|
|
|
rule_name,
|
|
|
|
Rule {
|
|
|
|
Rule {
|
|
|
|
head: rule_head,
|
|
|
|
head: rule_head,
|
|
|
|
body: rule_body,
|
|
|
|
body: rule_body,
|
|
|
|
vld,
|
|
|
|
vld,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
))
|
|
|
|
)))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn reorder_rule_body_for_negations(clauses: Vec<Atom>) -> Result<Vec<Atom>> {
|
|
|
|
fn reorder_rule_body_for_negations(clauses: Vec<Atom>) -> Result<Vec<Atom>> {
|
|
|
|
let (predicates, others): (Vec<_>, _) = clauses.into_iter().partition(|a| a.is_predicate());
|
|
|
|
let (negations, others): (Vec<_>, _) = clauses.into_iter().partition(|a| a.is_negation());
|
|
|
|
let mut predicates_with_meta = predicates
|
|
|
|
let mut seen_bindings = BTreeSet::new();
|
|
|
|
|
|
|
|
for a in &others {
|
|
|
|
|
|
|
|
a.collect_bindings(&mut seen_bindings);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut negations_with_meta = negations
|
|
|
|
.into_iter()
|
|
|
|
.into_iter()
|
|
|
|
.map(|p| {
|
|
|
|
.map(|p| {
|
|
|
|
let p = p.into_predicate().unwrap();
|
|
|
|
let p = p.into_negation().unwrap();
|
|
|
|
let bindings = p.bindings();
|
|
|
|
let mut bindings = Default::default();
|
|
|
|
(Some(p), bindings)
|
|
|
|
p.collect_bindings(&mut bindings);
|
|
|
|
|
|
|
|
let valid_bindings: BTreeSet<_> = bindings.intersection(&seen_bindings).cloned().collect();
|
|
|
|
|
|
|
|
(Some(p), valid_bindings)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.collect_vec();
|
|
|
|
.collect_vec();
|
|
|
|
let mut seen_bindings = BTreeSet::new();
|
|
|
|
|
|
|
|
let mut ret = vec![];
|
|
|
|
let mut ret = vec![];
|
|
|
|
|
|
|
|
seen_bindings.clear();
|
|
|
|
for a in others {
|
|
|
|
for a in others {
|
|
|
|
a.collect_bindings(&mut seen_bindings);
|
|
|
|
a.collect_bindings(&mut seen_bindings);
|
|
|
|
ret.push(a);
|
|
|
|
ret.push(a);
|
|
|
|
for (pred, pred_bindings) in predicates_with_meta.iter_mut() {
|
|
|
|
for (negated, pred_bindings) in negations_with_meta.iter_mut() {
|
|
|
|
if pred.is_none() {
|
|
|
|
if negated.is_none() {
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if seen_bindings.is_superset(pred_bindings) {
|
|
|
|
if seen_bindings.is_superset(pred_bindings) {
|
|
|
|
let pred = pred.take().unwrap();
|
|
|
|
let negated = negated.take().unwrap();
|
|
|
|
ret.push(Atom::Predicate(pred));
|
|
|
|
ret.push(Atom::Logical(LogicalAtom::Negation(Box::new(negated))));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (p, bindings) in predicates_with_meta {
|
|
|
|
Ok(ret)
|
|
|
|
if let Some(p) = p {
|
|
|
|
|
|
|
|
let diff = bindings.difference(&seen_bindings).cloned().collect();
|
|
|
|
|
|
|
|
return Err(QueryCompilationError::UnsafeBindingInPredicate(p, diff).into());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ok(ret)
|
|
|
|
|
|
|
|
todo!()
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn reorder_rule_body_for_predicates(clauses: Vec<Atom>) -> Result<Vec<Atom>> {
|
|
|
|
fn reorder_rule_body_for_predicates(clauses: Vec<Atom>) -> Result<Vec<Atom>> {
|
|
|
|
let (predicates, others): (Vec<_>, _) = clauses.into_iter().partition(|a| a.is_predicate());
|
|
|
|
let (predicates, others): (Vec<_>, _) = clauses.into_iter().partition(|a| a.is_predicate());
|
|
|
|
let mut predicates_with_meta = predicates
|
|
|
|
let mut predicates_with_meta = predicates
|
|
|
|