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:
Richard Newman 2017-04-05 13:08:01 -07:00
parent 0639c94468
commit 72977f52e4
3 changed files with 45 additions and 0 deletions

View file

@ -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:
/// ///

View file

@ -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));
}
} }

View file

@ -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 {