Support :db/noHistory for attributes. (#622) r=nalexander
At this point we never discard history, but this completes the API support for doing so.
This commit is contained in:
parent
9cc5cbf288
commit
6c54e1d370
5 changed files with 56 additions and 7 deletions
|
@ -700,6 +700,9 @@ pub struct Attribute {
|
|||
/// They are used to compose entities from component sub-entities: they are fetched recursively
|
||||
/// by pull expressions, and they are automatically recursively deleted where appropriate.
|
||||
pub component: bool,
|
||||
|
||||
/// `true` if this attribute doesn't require history to be kept, i.e., it is `:db/noHistory true`.
|
||||
pub no_history: bool,
|
||||
}
|
||||
|
||||
impl Attribute {
|
||||
|
@ -750,6 +753,10 @@ impl Attribute {
|
|||
attribute_map.insert(values::DB_IS_COMPONENT.clone(), edn::Value::Boolean(true));
|
||||
}
|
||||
|
||||
if self.no_history {
|
||||
attribute_map.insert(values::DB_NO_HISTORY.clone(), edn::Value::Boolean(true));
|
||||
}
|
||||
|
||||
edn::Value::Map(attribute_map)
|
||||
}
|
||||
}
|
||||
|
@ -764,6 +771,7 @@ impl Default for Attribute {
|
|||
multival: false,
|
||||
unique: None,
|
||||
component: false,
|
||||
no_history: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -894,6 +902,7 @@ mod test {
|
|||
unique: None,
|
||||
multival: false,
|
||||
component: false,
|
||||
no_history: false,
|
||||
};
|
||||
|
||||
assert!(attr1.flags() & AttributeBitFlags::IndexAVET as u8 != 0);
|
||||
|
@ -908,6 +917,7 @@ mod test {
|
|||
unique: Some(attribute::Unique::Value),
|
||||
multival: false,
|
||||
component: false,
|
||||
no_history: false,
|
||||
};
|
||||
|
||||
assert!(attr2.flags() & AttributeBitFlags::IndexAVET as u8 == 0);
|
||||
|
@ -922,6 +932,7 @@ mod test {
|
|||
unique: Some(attribute::Unique::Identity),
|
||||
multival: false,
|
||||
component: false,
|
||||
no_history: false,
|
||||
};
|
||||
|
||||
assert!(attr3.flags() & AttributeBitFlags::IndexAVET as u8 == 0);
|
||||
|
@ -954,6 +965,7 @@ mod test {
|
|||
unique: None,
|
||||
multival: false,
|
||||
component: false,
|
||||
no_history: true,
|
||||
};
|
||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 97);
|
||||
add_attribute(&mut schema, 97, attr1);
|
||||
|
@ -965,6 +977,7 @@ mod test {
|
|||
unique: Some(attribute::Unique::Value),
|
||||
multival: true,
|
||||
component: false,
|
||||
no_history: false,
|
||||
};
|
||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bas"), 98);
|
||||
add_attribute(&mut schema, 98, attr2);
|
||||
|
@ -976,6 +989,7 @@ mod test {
|
|||
unique: Some(attribute::Unique::Identity),
|
||||
multival: false,
|
||||
component: true,
|
||||
no_history: false,
|
||||
};
|
||||
|
||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bat"), 99);
|
||||
|
@ -986,7 +1000,8 @@ mod test {
|
|||
let expected_output = r#"[ { :db/ident :foo/bar
|
||||
:db/valueType :db.type/ref
|
||||
:db/cardinality :db.cardinality/one
|
||||
:db/index true },
|
||||
:db/index true
|
||||
:db/noHistory true },
|
||||
{ :db/ident :foo/bas
|
||||
:db/valueType :db.type/string
|
||||
:db/cardinality :db.cardinality/many
|
||||
|
|
|
@ -47,6 +47,7 @@ lazy_static_namespaced_keyword_value!(DB_IDENT, "db", "ident");
|
|||
lazy_static_namespaced_keyword_value!(DB_INDEX, "db", "index");
|
||||
lazy_static_namespaced_keyword_value!(DB_INSTALL_ATTRIBUTE, "db.install", "attribute");
|
||||
lazy_static_namespaced_keyword_value!(DB_IS_COMPONENT, "db", "component");
|
||||
lazy_static_namespaced_keyword_value!(DB_NO_HISTORY, "db", "noHistory");
|
||||
lazy_static_namespaced_keyword_value!(DB_PART_DB, "db.part", "db");
|
||||
lazy_static_namespaced_keyword_value!(DB_RETRACT, "db", "retract");
|
||||
lazy_static_namespaced_keyword_value!(DB_TYPE_BOOLEAN, "db.type", "boolean");
|
||||
|
|
|
@ -171,6 +171,13 @@ pub fn update_attribute_map_from_entid_triples<U>(attribute_map: &mut AttributeM
|
|||
}
|
||||
},
|
||||
|
||||
entids::DB_NO_HISTORY => {
|
||||
match *value {
|
||||
TypedValue::Boolean(x) => { builder.no_history(x); },
|
||||
_ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/noHistory true|false] but got [... :db/noHistory {:?}]", value)))
|
||||
}
|
||||
},
|
||||
|
||||
_ => {
|
||||
bail!(ErrorKind::BadSchemaAssertion(format!("Do not recognize attribute {} for entid {}", attr, entid)))
|
||||
}
|
||||
|
|
|
@ -79,6 +79,7 @@ pub struct AttributeBuilder {
|
|||
index: Option<bool>,
|
||||
fulltext: Option<bool>,
|
||||
component: Option<bool>,
|
||||
no_history: Option<bool>,
|
||||
}
|
||||
|
||||
impl AttributeBuilder {
|
||||
|
@ -127,6 +128,11 @@ impl AttributeBuilder {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn no_history<'a>(&'a mut self, no_history: bool) -> &'a mut Self {
|
||||
self.no_history = Some(no_history);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn validate_install_attribute(&self) -> Result<()> {
|
||||
if self.value_type.is_none() {
|
||||
bail!(ErrorKind::BadSchemaAssertion("Schema attribute for new attribute does not set :db/valueType".into()));
|
||||
|
@ -164,6 +170,9 @@ impl AttributeBuilder {
|
|||
if let Some(component) = self.component {
|
||||
attribute.component = component;
|
||||
}
|
||||
if let Some(no_history) = self.no_history {
|
||||
attribute.no_history = no_history;
|
||||
}
|
||||
|
||||
attribute
|
||||
}
|
||||
|
@ -194,6 +203,12 @@ impl AttributeBuilder {
|
|||
mutations.push(AttributeAlteration::IsComponent);
|
||||
}
|
||||
}
|
||||
if let Some(no_history) = self.no_history {
|
||||
if no_history != attribute.no_history {
|
||||
attribute.no_history = no_history;
|
||||
mutations.push(AttributeAlteration::NoHistory);
|
||||
}
|
||||
}
|
||||
|
||||
mutations
|
||||
}
|
||||
|
@ -326,6 +341,7 @@ mod test {
|
|||
unique: None,
|
||||
multival: false,
|
||||
component: false,
|
||||
no_history: false,
|
||||
});
|
||||
// attribute is unique by value and an index
|
||||
add_attribute(&mut schema, NamespacedKeyword::new("foo", "baz"), 98, Attribute {
|
||||
|
@ -335,6 +351,7 @@ mod test {
|
|||
unique: Some(attribute::Unique::Value),
|
||||
multival: false,
|
||||
component: false,
|
||||
no_history: false,
|
||||
});
|
||||
// attribue is unique by identity and an index
|
||||
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bat"), 99, Attribute {
|
||||
|
@ -344,6 +361,7 @@ mod test {
|
|||
unique: Some(attribute::Unique::Identity),
|
||||
multival: false,
|
||||
component: false,
|
||||
no_history: false,
|
||||
});
|
||||
// attribute is a components and a `Ref`
|
||||
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bak"), 100, Attribute {
|
||||
|
@ -353,6 +371,7 @@ mod test {
|
|||
unique: None,
|
||||
multival: false,
|
||||
component: true,
|
||||
no_history: false,
|
||||
});
|
||||
// fulltext attribute is a string and an index
|
||||
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bap"), 101, Attribute {
|
||||
|
@ -362,6 +381,7 @@ mod test {
|
|||
unique: None,
|
||||
multival: false,
|
||||
component: false,
|
||||
no_history: false,
|
||||
});
|
||||
|
||||
assert!(validate_attribute_map(&schema.entid_map, &schema.attribute_map).is_ok());
|
||||
|
@ -379,6 +399,7 @@ mod test {
|
|||
unique: Some(attribute::Unique::Value),
|
||||
multival: false,
|
||||
component: false,
|
||||
no_history: false,
|
||||
});
|
||||
|
||||
let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err();
|
||||
|
@ -401,6 +422,7 @@ mod test {
|
|||
unique: Some(attribute::Unique::Identity),
|
||||
multival: false,
|
||||
component: false,
|
||||
no_history: false,
|
||||
});
|
||||
|
||||
let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err();
|
||||
|
@ -423,6 +445,7 @@ mod test {
|
|||
unique: None,
|
||||
multival: false,
|
||||
component: true,
|
||||
no_history: false,
|
||||
});
|
||||
|
||||
let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err();
|
||||
|
@ -445,6 +468,7 @@ mod test {
|
|||
unique: None,
|
||||
multival: false,
|
||||
component: false,
|
||||
no_history: false,
|
||||
});
|
||||
|
||||
let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err();
|
||||
|
@ -466,6 +490,7 @@ mod test {
|
|||
unique: None,
|
||||
multival: false,
|
||||
component: false,
|
||||
no_history: false,
|
||||
});
|
||||
|
||||
let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err();
|
||||
|
|
|
@ -207,10 +207,9 @@ lazy_static! {
|
|||
kw!(:db.cardinality/many)
|
||||
};
|
||||
|
||||
// Not yet supported.
|
||||
// static ref DB_NO_HISTORY: NamespacedKeyword = {
|
||||
// NamespacedKeyword::new("db", "noHistory")
|
||||
// };
|
||||
static ref DB_NO_HISTORY: NamespacedKeyword = {
|
||||
NamespacedKeyword::new("db", "noHistory")
|
||||
};
|
||||
}
|
||||
|
||||
trait HasCoreSchema {
|
||||
|
@ -260,8 +259,7 @@ impl Definition {
|
|||
let a_value_type = via.core_attribute(&DB_VALUE_TYPE)?;
|
||||
let a_unique = via.core_attribute(&DB_UNIQUE)?;
|
||||
|
||||
// Not yet supported.
|
||||
// let a_no_history = via.core_attribute(&DB_NO_HISTORY)?;
|
||||
let a_no_history = via.core_attribute(&DB_NO_HISTORY)?;
|
||||
|
||||
let v_cardinality_many = via.core_entid(&DB_CARDINALITY_MANY)?;
|
||||
let v_cardinality_one = via.core_entid(&DB_CARDINALITY_ONE)?;
|
||||
|
@ -310,6 +308,9 @@ impl Definition {
|
|||
if attr.component {
|
||||
builder.add(tempid.clone(), a_is_component, TypedValue::Boolean(true))?;
|
||||
}
|
||||
if attr.no_history {
|
||||
builder.add(tempid.clone(), a_no_history, TypedValue::Boolean(true))?;
|
||||
}
|
||||
|
||||
if let Some(u) = attr.unique {
|
||||
let uu = match u {
|
||||
|
|
Loading…
Reference in a new issue