Expose component_attributes on Schema. (#623) r=nalexander

Some parts of the query engine and transactor need to know whether an
attribute is a component attribute, and sometimes want to do so in
a generated SQL query. This is one way to do that.
This commit is contained in:
Richard Newman 2018-04-03 14:25:53 -07:00 committed by GitHub
parent 558906df4f
commit 4d8e179a59
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 7 deletions

View file

@ -809,6 +809,10 @@ pub struct Schema {
/// Invariant: key-set is the same as the key-set of `entid_map` (equivalently, the value-set of
/// `ident_map`).
pub attribute_map: AttributeMap,
/// Maintain a vec of unique attribute IDs for which the corresponding attribute in `attribute_map`
/// has `.component == true`.
pub component_attributes: Vec<Entid>,
}
pub trait HasSchema {
@ -826,9 +830,17 @@ pub trait HasSchema {
/// Return true if the provided ident identifies an attribute in this schema.
fn identifies_attribute(&self, x: &NamespacedKeyword) -> bool;
fn component_attributes(&self) -> &[Entid];
}
impl Schema {
pub fn new(ident_map: IdentMap, entid_map: EntidMap, attribute_map: AttributeMap) -> Schema {
let mut s = Schema { ident_map, entid_map, attribute_map, component_attributes: Vec::new() };
s.update_component_attributes();
s
}
/// Returns an symbolic representation of the schema suitable for applying across Mentat stores.
pub fn to_edn_value(&self) -> edn::Value {
edn::Value::Vector((&self.attribute_map).iter()
@ -840,6 +852,16 @@ impl Schema {
fn get_raw_entid(&self, x: &NamespacedKeyword) -> Option<Entid> {
self.ident_map.get(x).map(|x| *x)
}
pub fn update_component_attributes(&mut self) {
let mut components: Vec<Entid>;
components = self.attribute_map
.iter()
.filter_map(|(k, v)| if v.component { Some(*k) } else { None })
.collect();
components.sort_unstable();
self.component_attributes = components;
}
}
impl HasSchema for Schema {
@ -876,6 +898,10 @@ impl HasSchema for Schema {
fn identifies_attribute(&self, x: &NamespacedKeyword) -> bool {
self.get_raw_entid(x).map(|e| self.is_attribute(e)).unwrap_or(false)
}
fn component_attributes(&self) -> &[Entid] {
&self.component_attributes
}
}
#[cfg(test)]

View file

@ -91,6 +91,13 @@ pub struct MetadataReport {
pub idents_altered: BTreeMap<Entid, IdentAlteration>,
}
impl MetadataReport {
pub fn attributes_did_change(&self) -> bool {
!(self.attributes_installed.is_empty() &&
self.attributes_altered.is_empty())
}
}
/// Update a `AttributeMap` in place from the given `[e a typed_value]` triples.
///
/// This is suitable for producing a `AttributeMap` from the `schema` materialized view, which does not
@ -284,6 +291,10 @@ pub fn update_schema_from_entid_quadruples<U>(schema: &mut Schema, assertions: U
idents_altered.insert(entid, IdentAlteration::Ident(ident.clone()));
}
if report.attributes_did_change() {
schema.update_component_attributes();
}
Ok(MetadataReport {
idents_altered: idents_altered,
.. report

View file

@ -241,12 +241,7 @@ impl SchemaBuilding for Schema {
let entid_map: EntidMap = ident_map.iter().map(|(k, v)| (v.clone(), k.clone())).collect();
validate_attribute_map(&entid_map, &attribute_map)?;
Ok(Schema {
ident_map: ident_map,
entid_map: entid_map,
attribute_map: attribute_map,
})
Ok(Schema::new(ident_map, entid_map, attribute_map))
}
/// Turn vec![(NamespacedKeyword(:ident), NamespacedKeyword(:key), TypedValue(:value)), ...] into a Mentat `Schema`.
@ -258,8 +253,14 @@ impl SchemaBuilding for Schema {
let attr: i64 = *ident_map.get(&symbolic_attr).ok_or(ErrorKind::UnrecognizedIdent(symbolic_attr.to_string()))?;
Ok((ident, attr, value))
}).collect();
let mut schema = Schema::from_ident_map_and_attribute_map(ident_map, AttributeMap::default())?;
metadata::update_attribute_map_from_entid_triples(&mut schema.attribute_map, entid_assertions?)?;
let metadata_report = metadata::update_attribute_map_from_entid_triples(&mut schema.attribute_map, entid_assertions?)?;
// Rebuild the component attributes list if necessary.
if metadata_report.attributes_did_change() {
schema.update_component_attributes();
}
Ok(schema)
}
}
@ -327,6 +328,10 @@ mod test {
schema.entid_map.insert(entid, ident.clone());
schema.ident_map.insert(ident.clone(), entid);
if attribute.component {
schema.component_attributes.push(entid);
}
schema.attribute_map.insert(entid, attribute);
}

View file

@ -336,6 +336,10 @@ impl<'a, 'c> HasSchema for InProgressRead<'a, 'c> {
fn identifies_attribute(&self, x: &NamespacedKeyword) -> bool {
self.0.identifies_attribute(x)
}
fn component_attributes(&self) -> &[Entid] {
self.0.component_attributes()
}
}
impl<'a, 'c> HasSchema for InProgress<'a, 'c> {
@ -368,6 +372,10 @@ impl<'a, 'c> HasSchema for InProgress<'a, 'c> {
fn identifies_attribute(&self, x: &NamespacedKeyword) -> bool {
self.schema.identifies_attribute(x)
}
fn component_attributes(&self) -> &[Entid] {
self.schema.component_attributes()
}
}