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:
parent
558906df4f
commit
4d8e179a59
4 changed files with 57 additions and 7 deletions
|
@ -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)]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue