Part 3: reinstate extracted type pruning.
When we started expanding and narrowing type sets, it became impossible to conclusively know during pattern application whether a type was known. We now figure that out at the end: if a variable has only a single known type, we don't need to extract its type tag.
This commit is contained in:
parent
0639c94468
commit
72977f52e4
3 changed files with 45 additions and 0 deletions
|
@ -648,6 +648,19 @@ impl ConjoiningClauses {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Eliminate any type extractions for variables whose types are definitely known.
|
||||||
|
pub fn prune_extracted_types(&mut self) {
|
||||||
|
if self.extracted_types.is_empty() || self.known_types.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (var, types) in self.known_types.iter() {
|
||||||
|
if types.len() == 1 {
|
||||||
|
self.extracted_types.remove(var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// When a CC has accumulated all patterns, generate value_type_tag entries in `wheres`
|
/// When a CC has accumulated all patterns, generate value_type_tag entries in `wheres`
|
||||||
/// to refine value types for which two things are true:
|
/// to refine value types for which two things are true:
|
||||||
///
|
///
|
||||||
|
|
|
@ -265,6 +265,8 @@ impl ConjoiningClauses {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod testing {
|
mod testing {
|
||||||
|
extern crate mentat_query_parser;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
@ -281,6 +283,10 @@ mod testing {
|
||||||
Variable,
|
Variable,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use self::mentat_query_parser::{
|
||||||
|
parse_find_string,
|
||||||
|
};
|
||||||
|
|
||||||
use clauses::{
|
use clauses::{
|
||||||
add_attribute,
|
add_attribute,
|
||||||
associate_ident,
|
associate_ident,
|
||||||
|
@ -296,6 +302,13 @@ mod testing {
|
||||||
SourceAlias,
|
SourceAlias,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use algebrize;
|
||||||
|
|
||||||
|
fn alg(schema: &Schema, input: &str) -> ConjoiningClauses {
|
||||||
|
let parsed = parse_find_string(input).expect("parse failed");
|
||||||
|
algebrize(schema.into(), parsed).expect("algebrize failed").cc
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_unknown_ident() {
|
fn test_unknown_ident() {
|
||||||
let mut cc = ConjoiningClauses::default();
|
let mut cc = ConjoiningClauses::default();
|
||||||
|
@ -815,4 +828,22 @@ mod testing {
|
||||||
assert_eq!(cc.empty_because.unwrap(),
|
assert_eq!(cc.empty_because.unwrap(),
|
||||||
EmptyBecause::TypeMismatch(x.clone(), unit_type_set(ValueType::Ref), ValueType::Boolean));
|
EmptyBecause::TypeMismatch(x.clone(), unit_type_set(ValueType::Ref), ValueType::Boolean));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ensure_extracted_types_is_cleared() {
|
||||||
|
let query = r#"[:find ?e ?v :where [_ _ ?v] [?e :foo/bar ?v]]"#;
|
||||||
|
let mut schema = Schema::default();
|
||||||
|
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99);
|
||||||
|
add_attribute(&mut schema, 99, Attribute {
|
||||||
|
value_type: ValueType::Boolean,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
let e = Variable::from_valid_name("?e");
|
||||||
|
let v = Variable::from_valid_name("?v");
|
||||||
|
let cc = alg(&schema, query);
|
||||||
|
assert_eq!(cc.known_types.get(&e), Some(&unit_type_set(ValueType::Ref)));
|
||||||
|
assert_eq!(cc.known_types.get(&v), Some(&unit_type_set(ValueType::Boolean)));
|
||||||
|
assert!(!cc.extracted_types.contains_key(&e));
|
||||||
|
assert!(!cc.extracted_types.contains_key(&v));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,7 @@ pub fn algebrize(schema: &Schema, parsed: FindQuery) -> Result<AlgebraicQuery> {
|
||||||
cc.apply_clause(schema, where_clause)?;
|
cc.apply_clause(schema, where_clause)?;
|
||||||
}
|
}
|
||||||
cc.expand_column_bindings();
|
cc.expand_column_bindings();
|
||||||
|
cc.prune_extracted_types();
|
||||||
|
|
||||||
let limit = if parsed.find_spec.is_unit_limited() { Some(1) } else { None };
|
let limit = if parsed.find_spec.is_unit_limited() { Some(1) } else { None };
|
||||||
Ok(AlgebraicQuery {
|
Ok(AlgebraicQuery {
|
||||||
|
|
Loading…
Reference in a new issue