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 /// Invariant: key-set is the same as the key-set of `entid_map` (equivalently, the value-set of
/// `ident_map`). /// `ident_map`).
pub attribute_map: AttributeMap, 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 { pub trait HasSchema {
@ -826,9 +830,17 @@ pub trait HasSchema {
/// Return true if the provided ident identifies an attribute in this schema. /// Return true if the provided ident identifies an attribute in this schema.
fn identifies_attribute(&self, x: &NamespacedKeyword) -> bool; fn identifies_attribute(&self, x: &NamespacedKeyword) -> bool;
fn component_attributes(&self) -> &[Entid];
} }
impl Schema { 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. /// Returns an symbolic representation of the schema suitable for applying across Mentat stores.
pub fn to_edn_value(&self) -> edn::Value { pub fn to_edn_value(&self) -> edn::Value {
edn::Value::Vector((&self.attribute_map).iter() edn::Value::Vector((&self.attribute_map).iter()
@ -840,6 +852,16 @@ impl Schema {
fn get_raw_entid(&self, x: &NamespacedKeyword) -> Option<Entid> { fn get_raw_entid(&self, x: &NamespacedKeyword) -> Option<Entid> {
self.ident_map.get(x).map(|x| *x) 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 { impl HasSchema for Schema {
@ -876,6 +898,10 @@ impl HasSchema for Schema {
fn identifies_attribute(&self, x: &NamespacedKeyword) -> bool { fn identifies_attribute(&self, x: &NamespacedKeyword) -> bool {
self.get_raw_entid(x).map(|e| self.is_attribute(e)).unwrap_or(false) self.get_raw_entid(x).map(|e| self.is_attribute(e)).unwrap_or(false)
} }
fn component_attributes(&self) -> &[Entid] {
&self.component_attributes
}
} }
#[cfg(test)] #[cfg(test)]

View file

@ -91,6 +91,13 @@ pub struct MetadataReport {
pub idents_altered: BTreeMap<Entid, IdentAlteration>, 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. /// 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 /// 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())); idents_altered.insert(entid, IdentAlteration::Ident(ident.clone()));
} }
if report.attributes_did_change() {
schema.update_component_attributes();
}
Ok(MetadataReport { Ok(MetadataReport {
idents_altered: idents_altered, idents_altered: idents_altered,
.. report .. 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(); let entid_map: EntidMap = ident_map.iter().map(|(k, v)| (v.clone(), k.clone())).collect();
validate_attribute_map(&entid_map, &attribute_map)?; validate_attribute_map(&entid_map, &attribute_map)?;
Ok(Schema::new(ident_map, entid_map, attribute_map))
Ok(Schema {
ident_map: ident_map,
entid_map: entid_map,
attribute_map: attribute_map,
})
} }
/// Turn vec![(NamespacedKeyword(:ident), NamespacedKeyword(:key), TypedValue(:value)), ...] into a Mentat `Schema`. /// 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()))?; let attr: i64 = *ident_map.get(&symbolic_attr).ok_or(ErrorKind::UnrecognizedIdent(symbolic_attr.to_string()))?;
Ok((ident, attr, value)) Ok((ident, attr, value))
}).collect(); }).collect();
let mut schema = Schema::from_ident_map_and_attribute_map(ident_map, AttributeMap::default())?; 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) Ok(schema)
} }
} }
@ -327,6 +328,10 @@ mod test {
schema.entid_map.insert(entid, ident.clone()); schema.entid_map.insert(entid, ident.clone());
schema.ident_map.insert(ident.clone(), entid); schema.ident_map.insert(ident.clone(), entid);
if attribute.component {
schema.component_attributes.push(entid);
}
schema.attribute_map.insert(entid, attribute); 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 { fn identifies_attribute(&self, x: &NamespacedKeyword) -> bool {
self.0.identifies_attribute(x) self.0.identifies_attribute(x)
} }
fn component_attributes(&self) -> &[Entid] {
self.0.component_attributes()
}
} }
impl<'a, 'c> HasSchema for InProgress<'a, 'c> { 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 { fn identifies_attribute(&self, x: &NamespacedKeyword) -> bool {
self.schema.identifies_attribute(x) self.schema.identifies_attribute(x)
} }
fn component_attributes(&self) -> &[Entid] {
self.schema.component_attributes()
}
} }