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:
Richard Newman 2018-04-03 14:23:46 -07:00 committed by GitHub
parent 9cc5cbf288
commit 6c54e1d370
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 7 deletions

View file

@ -700,6 +700,9 @@ pub struct Attribute {
/// They are used to compose entities from component sub-entities: they are fetched recursively /// 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. /// by pull expressions, and they are automatically recursively deleted where appropriate.
pub component: bool, 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 { impl Attribute {
@ -750,6 +753,10 @@ impl Attribute {
attribute_map.insert(values::DB_IS_COMPONENT.clone(), edn::Value::Boolean(true)); 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) edn::Value::Map(attribute_map)
} }
} }
@ -764,6 +771,7 @@ impl Default for Attribute {
multival: false, multival: false,
unique: None, unique: None,
component: false, component: false,
no_history: false,
} }
} }
} }
@ -894,6 +902,7 @@ mod test {
unique: None, unique: None,
multival: false, multival: false,
component: false, component: false,
no_history: false,
}; };
assert!(attr1.flags() & AttributeBitFlags::IndexAVET as u8 != 0); assert!(attr1.flags() & AttributeBitFlags::IndexAVET as u8 != 0);
@ -908,6 +917,7 @@ mod test {
unique: Some(attribute::Unique::Value), unique: Some(attribute::Unique::Value),
multival: false, multival: false,
component: false, component: false,
no_history: false,
}; };
assert!(attr2.flags() & AttributeBitFlags::IndexAVET as u8 == 0); assert!(attr2.flags() & AttributeBitFlags::IndexAVET as u8 == 0);
@ -922,6 +932,7 @@ mod test {
unique: Some(attribute::Unique::Identity), unique: Some(attribute::Unique::Identity),
multival: false, multival: false,
component: false, component: false,
no_history: false,
}; };
assert!(attr3.flags() & AttributeBitFlags::IndexAVET as u8 == 0); assert!(attr3.flags() & AttributeBitFlags::IndexAVET as u8 == 0);
@ -954,6 +965,7 @@ mod test {
unique: None, unique: None,
multival: false, multival: false,
component: false, component: false,
no_history: true,
}; };
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 97); associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 97);
add_attribute(&mut schema, 97, attr1); add_attribute(&mut schema, 97, attr1);
@ -965,6 +977,7 @@ mod test {
unique: Some(attribute::Unique::Value), unique: Some(attribute::Unique::Value),
multival: true, multival: true,
component: false, component: false,
no_history: false,
}; };
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bas"), 98); associate_ident(&mut schema, NamespacedKeyword::new("foo", "bas"), 98);
add_attribute(&mut schema, 98, attr2); add_attribute(&mut schema, 98, attr2);
@ -976,6 +989,7 @@ mod test {
unique: Some(attribute::Unique::Identity), unique: Some(attribute::Unique::Identity),
multival: false, multival: false,
component: true, component: true,
no_history: false,
}; };
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bat"), 99); associate_ident(&mut schema, NamespacedKeyword::new("foo", "bat"), 99);
@ -986,7 +1000,8 @@ mod test {
let expected_output = r#"[ { :db/ident :foo/bar let expected_output = r#"[ { :db/ident :foo/bar
:db/valueType :db.type/ref :db/valueType :db.type/ref
:db/cardinality :db.cardinality/one :db/cardinality :db.cardinality/one
:db/index true }, :db/index true
:db/noHistory true },
{ :db/ident :foo/bas { :db/ident :foo/bas
:db/valueType :db.type/string :db/valueType :db.type/string
:db/cardinality :db.cardinality/many :db/cardinality :db.cardinality/many

View file

@ -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_INDEX, "db", "index");
lazy_static_namespaced_keyword_value!(DB_INSTALL_ATTRIBUTE, "db.install", "attribute"); 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_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_PART_DB, "db.part", "db");
lazy_static_namespaced_keyword_value!(DB_RETRACT, "db", "retract"); lazy_static_namespaced_keyword_value!(DB_RETRACT, "db", "retract");
lazy_static_namespaced_keyword_value!(DB_TYPE_BOOLEAN, "db.type", "boolean"); lazy_static_namespaced_keyword_value!(DB_TYPE_BOOLEAN, "db.type", "boolean");

View file

@ -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))) bail!(ErrorKind::BadSchemaAssertion(format!("Do not recognize attribute {} for entid {}", attr, entid)))
} }

View file

@ -79,6 +79,7 @@ pub struct AttributeBuilder {
index: Option<bool>, index: Option<bool>,
fulltext: Option<bool>, fulltext: Option<bool>,
component: Option<bool>, component: Option<bool>,
no_history: Option<bool>,
} }
impl AttributeBuilder { impl AttributeBuilder {
@ -127,6 +128,11 @@ impl AttributeBuilder {
self 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<()> { pub fn validate_install_attribute(&self) -> Result<()> {
if self.value_type.is_none() { if self.value_type.is_none() {
bail!(ErrorKind::BadSchemaAssertion("Schema attribute for new attribute does not set :db/valueType".into())); 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 { if let Some(component) = self.component {
attribute.component = component; attribute.component = component;
} }
if let Some(no_history) = self.no_history {
attribute.no_history = no_history;
}
attribute attribute
} }
@ -194,6 +203,12 @@ impl AttributeBuilder {
mutations.push(AttributeAlteration::IsComponent); 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 mutations
} }
@ -326,6 +341,7 @@ mod test {
unique: None, unique: None,
multival: false, multival: false,
component: false, component: false,
no_history: false,
}); });
// attribute is unique by value and an index // attribute is unique by value and an index
add_attribute(&mut schema, NamespacedKeyword::new("foo", "baz"), 98, Attribute { add_attribute(&mut schema, NamespacedKeyword::new("foo", "baz"), 98, Attribute {
@ -335,6 +351,7 @@ mod test {
unique: Some(attribute::Unique::Value), unique: Some(attribute::Unique::Value),
multival: false, multival: false,
component: false, component: false,
no_history: false,
}); });
// attribue is unique by identity and an index // attribue is unique by identity and an index
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bat"), 99, Attribute { add_attribute(&mut schema, NamespacedKeyword::new("foo", "bat"), 99, Attribute {
@ -344,6 +361,7 @@ mod test {
unique: Some(attribute::Unique::Identity), unique: Some(attribute::Unique::Identity),
multival: false, multival: false,
component: false, component: false,
no_history: false,
}); });
// attribute is a components and a `Ref` // attribute is a components and a `Ref`
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bak"), 100, Attribute { add_attribute(&mut schema, NamespacedKeyword::new("foo", "bak"), 100, Attribute {
@ -353,6 +371,7 @@ mod test {
unique: None, unique: None,
multival: false, multival: false,
component: true, component: true,
no_history: false,
}); });
// fulltext attribute is a string and an index // fulltext attribute is a string and an index
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bap"), 101, Attribute { add_attribute(&mut schema, NamespacedKeyword::new("foo", "bap"), 101, Attribute {
@ -362,6 +381,7 @@ mod test {
unique: None, unique: None,
multival: false, multival: false,
component: false, component: false,
no_history: false,
}); });
assert!(validate_attribute_map(&schema.entid_map, &schema.attribute_map).is_ok()); assert!(validate_attribute_map(&schema.entid_map, &schema.attribute_map).is_ok());
@ -379,6 +399,7 @@ mod test {
unique: Some(attribute::Unique::Value), unique: Some(attribute::Unique::Value),
multival: false, multival: false,
component: false, component: false,
no_history: false,
}); });
let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err(); let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err();
@ -401,6 +422,7 @@ mod test {
unique: Some(attribute::Unique::Identity), unique: Some(attribute::Unique::Identity),
multival: false, multival: false,
component: false, component: false,
no_history: false,
}); });
let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err(); let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err();
@ -423,6 +445,7 @@ mod test {
unique: None, unique: None,
multival: false, multival: false,
component: true, component: true,
no_history: false,
}); });
let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err(); let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err();
@ -445,6 +468,7 @@ mod test {
unique: None, unique: None,
multival: false, multival: false,
component: false, component: false,
no_history: false,
}); });
let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err(); let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err();
@ -466,6 +490,7 @@ mod test {
unique: None, unique: None,
multival: false, multival: false,
component: false, component: false,
no_history: false,
}); });
let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err(); let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err();

View file

@ -207,10 +207,9 @@ lazy_static! {
kw!(:db.cardinality/many) kw!(:db.cardinality/many)
}; };
// Not yet supported. static ref DB_NO_HISTORY: NamespacedKeyword = {
// static ref DB_NO_HISTORY: NamespacedKeyword = { NamespacedKeyword::new("db", "noHistory")
// NamespacedKeyword::new("db", "noHistory") };
// };
} }
trait HasCoreSchema { trait HasCoreSchema {
@ -260,8 +259,7 @@ impl Definition {
let a_value_type = via.core_attribute(&DB_VALUE_TYPE)?; let a_value_type = via.core_attribute(&DB_VALUE_TYPE)?;
let a_unique = via.core_attribute(&DB_UNIQUE)?; 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_many = via.core_entid(&DB_CARDINALITY_MANY)?;
let v_cardinality_one = via.core_entid(&DB_CARDINALITY_ONE)?; let v_cardinality_one = via.core_entid(&DB_CARDINALITY_ONE)?;
@ -310,6 +308,9 @@ impl Definition {
if attr.component { if attr.component {
builder.add(tempid.clone(), a_is_component, TypedValue::Boolean(true))?; 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 { if let Some(u) = attr.unique {
let uu = match u { let uu = match u {