Preliminary work for vocabulary management. r=emily,nalexander
Pre: export AttributeBuilder from mentat_db. Pre: fix module-level comment for tx/src/entities.rs. Pre: rename some `to_` conversions to `into_`. Pre: make AttributeBuilder::unique less verbose. Pre: split out a HasSchema trait to abstract over Schema. Pre: rename SchemaMap/schema_map to AttributeMap/attribute_map. Pre: TypedValue/NamespacedKeyword conversions. Pre: turn Unique and ValueType into TypedValue::Keyword. Pre: export IntoResult. Pre: export NamespacedKeyword from mentat_core. Pre: use intern_set in tx. Pre: add InternSet::len. Pre: comment gardening. Pre: remove inaccurate TODO from TxReport comment.
This commit is contained in:
parent
224570fb45
commit
6797a606b5
22 changed files with 150 additions and 80 deletions
|
@ -33,6 +33,10 @@ impl<T> InternSet<T> where T: Eq + Hash {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.inner.len()
|
||||
}
|
||||
|
||||
/// Intern a value, providing a ref-counted handle to the interned value.
|
||||
///
|
||||
/// ```
|
||||
|
|
101
core/src/lib.rs
101
core/src/lib.rs
|
@ -31,9 +31,6 @@ use std::rc::Rc;
|
|||
use enum_set::EnumSet;
|
||||
|
||||
use self::ordered_float::OrderedFloat;
|
||||
use self::edn::{
|
||||
NamespacedKeyword,
|
||||
};
|
||||
|
||||
pub use uuid::Uuid;
|
||||
|
||||
|
@ -44,6 +41,7 @@ pub use chrono::{
|
|||
|
||||
pub use edn::{
|
||||
FromMicros,
|
||||
NamespacedKeyword,
|
||||
ToMicros,
|
||||
Utc,
|
||||
};
|
||||
|
@ -102,7 +100,33 @@ impl enum_set::CLike for ValueType {
|
|||
}
|
||||
|
||||
impl ValueType {
|
||||
pub fn to_edn_value(self) -> edn::Value {
|
||||
pub fn into_keyword(self) -> NamespacedKeyword {
|
||||
NamespacedKeyword::new("db.type", match self {
|
||||
ValueType::Ref => "ref",
|
||||
ValueType::Boolean => "boolean",
|
||||
ValueType::Instant => "instant",
|
||||
ValueType::Long => "long",
|
||||
ValueType::Double => "double",
|
||||
ValueType::String => "string",
|
||||
ValueType::Keyword => "keyword",
|
||||
ValueType::Uuid => "uuid",
|
||||
})
|
||||
}
|
||||
|
||||
pub fn into_typed_value(self) -> TypedValue {
|
||||
TypedValue::typed_ns_keyword("db.type", match self {
|
||||
ValueType::Ref => "ref",
|
||||
ValueType::Boolean => "boolean",
|
||||
ValueType::Instant => "instant",
|
||||
ValueType::Long => "long",
|
||||
ValueType::Double => "double",
|
||||
ValueType::String => "string",
|
||||
ValueType::Keyword => "keyword",
|
||||
ValueType::Uuid => "uuid",
|
||||
})
|
||||
}
|
||||
|
||||
pub fn into_edn_value(self) -> edn::Value {
|
||||
match self {
|
||||
ValueType::Ref => values::DB_TYPE_REF.clone(),
|
||||
ValueType::Boolean => values::DB_TYPE_BOOLEAN.clone(),
|
||||
|
@ -480,11 +504,23 @@ pub enum AttributeBitFlags {
|
|||
}
|
||||
|
||||
pub mod attribute {
|
||||
#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
|
||||
use TypedValue;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
||||
pub enum Unique {
|
||||
Value,
|
||||
Identity,
|
||||
}
|
||||
|
||||
impl Unique {
|
||||
// This is easier than rejigging DB_UNIQUE_VALUE to not be EDN.
|
||||
pub fn into_typed_value(self) -> TypedValue {
|
||||
match self {
|
||||
Unique::Value => TypedValue::typed_ns_keyword("db.unique", "value"),
|
||||
Unique::Identity => TypedValue::typed_ns_keyword("db.unique", "identity"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A Mentat schema attribute has a value type and several other flags determining how assertions
|
||||
|
@ -561,7 +597,7 @@ impl Attribute {
|
|||
attribute_map.insert(values::DB_IDENT.clone(), edn::Value::NamespacedKeyword(ident));
|
||||
}
|
||||
|
||||
attribute_map.insert(values::DB_VALUE_TYPE.clone(), self.value_type.to_edn_value());
|
||||
attribute_map.insert(values::DB_VALUE_TYPE.clone(), self.value_type.into_edn_value());
|
||||
|
||||
attribute_map.insert(values::DB_CARDINALITY.clone(), if self.multival { values::DB_CARDINALITY_MANY.clone() } else { values::DB_CARDINALITY_ONE.clone() });
|
||||
|
||||
|
@ -608,7 +644,7 @@ pub type IdentMap = BTreeMap<NamespacedKeyword, Entid>;
|
|||
pub type EntidMap = BTreeMap<Entid, NamespacedKeyword>;
|
||||
|
||||
/// Map attribute entids to `Attribute` instances.
|
||||
pub type SchemaMap = BTreeMap<Entid, Attribute>;
|
||||
pub type AttributeMap = BTreeMap<Entid, Attribute>;
|
||||
|
||||
/// Represents a Mentat schema.
|
||||
///
|
||||
|
@ -633,44 +669,59 @@ pub struct Schema {
|
|||
///
|
||||
/// Invariant: key-set is the same as the key-set of `entid_map` (equivalently, the value-set of
|
||||
/// `ident_map`).
|
||||
pub schema_map: SchemaMap,
|
||||
pub attribute_map: AttributeMap,
|
||||
}
|
||||
|
||||
pub trait HasSchema {
|
||||
fn get_ident(&self, x: Entid) -> Option<&NamespacedKeyword>;
|
||||
fn get_entid(&self, x: &NamespacedKeyword) -> Option<Entid>;
|
||||
fn attribute_for_entid(&self, x: Entid) -> Option<&Attribute>;
|
||||
fn attribute_for_ident(&self, ident: &NamespacedKeyword) -> Option<&Attribute>;
|
||||
|
||||
/// Return true if the provided entid identifies an attribute in this schema.
|
||||
fn is_attribute(&self, x: Entid) -> bool;
|
||||
|
||||
/// Return true if the provided ident identifies an attribute in this schema.
|
||||
fn identifies_attribute(&self, x: &NamespacedKeyword) -> bool;
|
||||
}
|
||||
|
||||
impl Schema {
|
||||
pub fn get_ident(&self, x: Entid) -> Option<&NamespacedKeyword> {
|
||||
/// 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()
|
||||
.map(|(entid, attribute)|
|
||||
attribute.to_edn_value(self.get_ident(*entid).cloned()))
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl HasSchema for Schema {
|
||||
fn get_ident(&self, x: Entid) -> Option<&NamespacedKeyword> {
|
||||
self.entid_map.get(&x)
|
||||
}
|
||||
|
||||
pub fn get_entid(&self, x: &NamespacedKeyword) -> Option<Entid> {
|
||||
fn get_entid(&self, x: &NamespacedKeyword) -> Option<Entid> {
|
||||
self.ident_map.get(x).map(|x| *x)
|
||||
}
|
||||
|
||||
pub fn attribute_for_entid(&self, x: Entid) -> Option<&Attribute> {
|
||||
self.schema_map.get(&x)
|
||||
fn attribute_for_entid(&self, x: Entid) -> Option<&Attribute> {
|
||||
self.attribute_map.get(&x)
|
||||
}
|
||||
|
||||
pub fn attribute_for_ident(&self, ident: &NamespacedKeyword) -> Option<&Attribute> {
|
||||
fn attribute_for_ident(&self, ident: &NamespacedKeyword) -> Option<&Attribute> {
|
||||
self.get_entid(&ident)
|
||||
.and_then(|x| self.attribute_for_entid(x))
|
||||
}
|
||||
|
||||
/// Return true if the provided entid identifies an attribute in this schema.
|
||||
pub fn is_attribute(&self, x: Entid) -> bool {
|
||||
self.schema_map.contains_key(&x)
|
||||
fn is_attribute(&self, x: Entid) -> bool {
|
||||
self.attribute_map.contains_key(&x)
|
||||
}
|
||||
|
||||
/// Return true if the provided ident identifies an attribute in this schema.
|
||||
pub fn identifies_attribute(&self, x: &NamespacedKeyword) -> bool {
|
||||
fn identifies_attribute(&self, x: &NamespacedKeyword) -> bool {
|
||||
self.get_entid(x).map(|e| self.is_attribute(e)).unwrap_or(false)
|
||||
}
|
||||
|
||||
/// 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.schema_map).iter()
|
||||
.map(|(entid, attribute)|
|
||||
attribute.to_edn_value(self.get_ident(*entid).cloned()))
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -685,7 +736,7 @@ mod test {
|
|||
}
|
||||
|
||||
fn add_attribute(schema: &mut Schema, e: Entid, a: Attribute) {
|
||||
schema.schema_map.insert(e, a);
|
||||
schema.attribute_map.insert(e, a);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
20
db/src/db.rs
20
db/src/db.rs
|
@ -44,7 +44,7 @@ use mentat_core::{
|
|||
FromMicros,
|
||||
IdentMap,
|
||||
Schema,
|
||||
SchemaMap,
|
||||
AttributeMap,
|
||||
TypedValue,
|
||||
ToMicros,
|
||||
ValueType,
|
||||
|
@ -479,11 +479,11 @@ fn read_ident_map(conn: &rusqlite::Connection) -> Result<IdentMap> {
|
|||
}
|
||||
|
||||
/// Read the schema materialized view from the given SQL store.
|
||||
fn read_schema_map(conn: &rusqlite::Connection) -> Result<SchemaMap> {
|
||||
fn read_attribute_map(conn: &rusqlite::Connection) -> Result<AttributeMap> {
|
||||
let entid_triples = read_materialized_view(conn, "schema")?;
|
||||
let mut schema_map = SchemaMap::default();
|
||||
metadata::update_schema_map_from_entid_triples(&mut schema_map, entid_triples)?;
|
||||
Ok(schema_map)
|
||||
let mut attribute_map = AttributeMap::default();
|
||||
metadata::update_attribute_map_from_entid_triples(&mut attribute_map, entid_triples)?;
|
||||
Ok(attribute_map)
|
||||
}
|
||||
|
||||
/// Read the materialized views from the given SQL store and return a Mentat `DB` for querying and
|
||||
|
@ -491,8 +491,8 @@ fn read_schema_map(conn: &rusqlite::Connection) -> Result<SchemaMap> {
|
|||
pub fn read_db(conn: &rusqlite::Connection) -> Result<DB> {
|
||||
let partition_map = read_partition_map(conn)?;
|
||||
let ident_map = read_ident_map(conn)?;
|
||||
let schema_map = read_schema_map(conn)?;
|
||||
let schema = Schema::from_ident_map_and_schema_map(ident_map, schema_map)?;
|
||||
let attribute_map = read_attribute_map(conn)?;
|
||||
let schema = Schema::from_ident_map_and_attribute_map(ident_map, attribute_map)?;
|
||||
Ok(DB::new(partition_map, schema))
|
||||
}
|
||||
|
||||
|
@ -1106,6 +1106,8 @@ mod tests {
|
|||
use debug;
|
||||
use edn;
|
||||
use mentat_core::{
|
||||
HasSchema,
|
||||
Schema,
|
||||
attribute,
|
||||
};
|
||||
use mentat_tx_parser;
|
||||
|
@ -1158,9 +1160,9 @@ mod tests {
|
|||
impl TestConn {
|
||||
fn assert_materialized_views(&self) {
|
||||
let materialized_ident_map = read_ident_map(&self.sqlite).expect("ident map");
|
||||
let materialized_schema_map = read_schema_map(&self.sqlite).expect("schema map");
|
||||
let materialized_attribute_map = read_attribute_map(&self.sqlite).expect("schema map");
|
||||
|
||||
let materialized_schema = Schema::from_ident_map_and_schema_map(materialized_ident_map, materialized_schema_map).expect("schema");
|
||||
let materialized_schema = Schema::from_ident_map_and_attribute_map(materialized_ident_map, materialized_attribute_map).expect("schema");
|
||||
assert_eq!(materialized_schema, self.schema);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ use edn;
|
|||
use entids;
|
||||
use errors::Result;
|
||||
use mentat_core::{
|
||||
HasSchema,
|
||||
SQLValueType,
|
||||
TypedValue,
|
||||
ValueType,
|
||||
|
|
|
@ -55,6 +55,8 @@ pub use bootstrap::{
|
|||
USER0,
|
||||
};
|
||||
|
||||
pub use schema::AttributeBuilder;
|
||||
|
||||
pub use db::{
|
||||
TypedSQLValue,
|
||||
new_connection,
|
||||
|
|
|
@ -43,7 +43,7 @@ use mentat_core::{
|
|||
attribute,
|
||||
Entid,
|
||||
Schema,
|
||||
SchemaMap,
|
||||
AttributeMap,
|
||||
TypedValue,
|
||||
ValueType,
|
||||
};
|
||||
|
@ -78,24 +78,24 @@ pub enum IdentAlteration {
|
|||
/// Summarizes changes to metadata such as a a `Schema` and (in the future) a `PartitionMap`.
|
||||
#[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
||||
pub struct MetadataReport {
|
||||
// Entids that were not present in the original `SchemaMap` that was mutated.
|
||||
// Entids that were not present in the original `AttributeMap` that was mutated.
|
||||
pub attributes_installed: BTreeSet<Entid>,
|
||||
|
||||
// Entids that were present in the original `SchemaMap` that was mutated, together with a
|
||||
// Entids that were present in the original `AttributeMap` that was mutated, together with a
|
||||
// representation of the mutations that were applied.
|
||||
pub attributes_altered: BTreeMap<Entid, Vec<AttributeAlteration>>,
|
||||
|
||||
// Idents that were installed into the `SchemaMap`.
|
||||
// Idents that were installed into the `AttributeMap`.
|
||||
pub idents_altered: BTreeMap<Entid, IdentAlteration>,
|
||||
}
|
||||
|
||||
/// Update a `SchemaMap` 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 `SchemaMap` from the `schema` materialized view, which does not
|
||||
/// This is suitable for producing a `AttributeMap` from the `schema` materialized view, which does not
|
||||
/// contain install and alter markers.
|
||||
///
|
||||
/// Returns a report summarizing the mutations that were applied.
|
||||
pub fn update_schema_map_from_entid_triples<U>(schema_map: &mut SchemaMap, assertions: U) -> Result<MetadataReport>
|
||||
pub fn update_attribute_map_from_entid_triples<U>(attribute_map: &mut AttributeMap, assertions: U) -> Result<MetadataReport>
|
||||
where U: IntoIterator<Item=(Entid, Entid, TypedValue)> {
|
||||
|
||||
// Group mutations by impacted entid.
|
||||
|
@ -142,8 +142,8 @@ pub fn update_schema_map_from_entid_triples<U>(schema_map: &mut SchemaMap, asser
|
|||
// builder.unique_value(false);
|
||||
// builder.unique_identity(false);
|
||||
// },
|
||||
TypedValue::Ref(entids::DB_UNIQUE_VALUE) => { builder.unique(Some(attribute::Unique::Value)); },
|
||||
TypedValue::Ref(entids::DB_UNIQUE_IDENTITY) => { builder.unique(Some(attribute::Unique::Identity)); },
|
||||
TypedValue::Ref(entids::DB_UNIQUE_VALUE) => { builder.unique(attribute::Unique::Value); },
|
||||
TypedValue::Ref(entids::DB_UNIQUE_IDENTITY) => { builder.unique(attribute::Unique::Identity); },
|
||||
_ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/unique :db.unique/value|:db.unique/identity] but got [... :db/unique {:?}]", value)))
|
||||
}
|
||||
},
|
||||
|
@ -179,7 +179,7 @@ pub fn update_schema_map_from_entid_triples<U>(schema_map: &mut SchemaMap, asser
|
|||
let mut attributes_altered: BTreeMap<Entid, Vec<AttributeAlteration>> = BTreeMap::default();
|
||||
|
||||
for (entid, builder) in builders.into_iter() {
|
||||
match schema_map.entry(entid) {
|
||||
match attribute_map.entry(entid) {
|
||||
Entry::Vacant(entry) => {
|
||||
builder.validate_install_attribute()
|
||||
.chain_err(|| ErrorKind::BadSchemaAssertion(format!("Schema alteration for new attribute with entid {} is not valid", entid)))?;
|
||||
|
@ -245,7 +245,7 @@ pub fn update_schema_from_entid_quadruples<U>(schema: &mut Schema, assertions: U
|
|||
let asserted_triples = attribute_set.asserted.into_iter().map(|((e, a), typed_value)| (e, a, typed_value));
|
||||
let altered_triples = attribute_set.altered.into_iter().map(|((e, a), (_old_value, new_value))| (e, a, new_value));
|
||||
|
||||
let report = update_schema_map_from_entid_triples(&mut schema.schema_map, asserted_triples.chain(altered_triples))?;
|
||||
let report = update_attribute_map_from_entid_triples(&mut schema.attribute_map, asserted_triples.chain(altered_triples))?;
|
||||
|
||||
let mut idents_altered: BTreeMap<Entid, IdentAlteration> = BTreeMap::new();
|
||||
|
||||
|
|
|
@ -19,9 +19,10 @@ use mentat_core::{
|
|||
Attribute,
|
||||
Entid,
|
||||
EntidMap,
|
||||
HasSchema,
|
||||
IdentMap,
|
||||
Schema,
|
||||
SchemaMap,
|
||||
AttributeMap,
|
||||
TypedValue,
|
||||
ValueType,
|
||||
};
|
||||
|
@ -30,9 +31,9 @@ use metadata::{
|
|||
AttributeAlteration,
|
||||
};
|
||||
|
||||
/// Return `Ok(())` if `schema_map` defines a valid Mentat schema.
|
||||
fn validate_schema_map(entid_map: &EntidMap, schema_map: &SchemaMap) -> Result<()> {
|
||||
for (entid, attribute) in schema_map {
|
||||
/// Return `Ok(())` if `attribute_map` defines a valid Mentat schema.
|
||||
fn validate_attribute_map(entid_map: &EntidMap, attribute_map: &AttributeMap) -> Result<()> {
|
||||
for (entid, attribute) in attribute_map {
|
||||
let ident = || entid_map.get(entid).map(|ident| ident.to_string()).unwrap_or(entid.to_string());
|
||||
if attribute.unique == Some(attribute::Unique::Value) && !attribute.index {
|
||||
bail!(ErrorKind::BadSchemaAssertion(format!(":db/unique :db/unique_value without :db/index true for entid: {}", ident())))
|
||||
|
@ -78,8 +79,8 @@ impl AttributeBuilder {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn unique<'a>(&'a mut self, unique: Option<attribute::Unique>) -> &'a mut Self {
|
||||
self.unique = Some(unique);
|
||||
pub fn unique<'a>(&'a mut self, unique: attribute::Unique) -> &'a mut Self {
|
||||
self.unique = Some(Some(unique));
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -174,7 +175,7 @@ pub trait SchemaBuilding {
|
|||
fn require_ident(&self, entid: Entid) -> Result<&symbols::NamespacedKeyword>;
|
||||
fn require_entid(&self, ident: &symbols::NamespacedKeyword) -> Result<Entid>;
|
||||
fn require_attribute_for_entid(&self, entid: Entid) -> Result<&Attribute>;
|
||||
fn from_ident_map_and_schema_map(ident_map: IdentMap, schema_map: SchemaMap) -> Result<Schema>;
|
||||
fn from_ident_map_and_attribute_map(ident_map: IdentMap, attribute_map: AttributeMap) -> Result<Schema>;
|
||||
fn from_ident_map_and_triples<U>(ident_map: IdentMap, assertions: U) -> Result<Schema>
|
||||
where U: IntoIterator<Item=(symbols::NamespacedKeyword, symbols::NamespacedKeyword, TypedValue)>;
|
||||
}
|
||||
|
@ -193,15 +194,15 @@ impl SchemaBuilding for Schema {
|
|||
}
|
||||
|
||||
/// Create a valid `Schema` from the constituent maps.
|
||||
fn from_ident_map_and_schema_map(ident_map: IdentMap, schema_map: SchemaMap) -> Result<Schema> {
|
||||
fn from_ident_map_and_attribute_map(ident_map: IdentMap, attribute_map: AttributeMap) -> Result<Schema> {
|
||||
let entid_map: EntidMap = ident_map.iter().map(|(k, v)| (v.clone(), k.clone())).collect();
|
||||
|
||||
validate_schema_map(&entid_map, &schema_map)?;
|
||||
validate_attribute_map(&entid_map, &attribute_map)?;
|
||||
|
||||
Ok(Schema {
|
||||
ident_map: ident_map,
|
||||
entid_map: entid_map,
|
||||
schema_map: schema_map,
|
||||
attribute_map: attribute_map,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -214,8 +215,8 @@ 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_schema_map(ident_map, SchemaMap::default())?;
|
||||
metadata::update_schema_map_from_entid_triples(&mut schema.schema_map, entid_assertions?)?;
|
||||
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?)?;
|
||||
Ok(schema)
|
||||
}
|
||||
}
|
||||
|
@ -283,11 +284,11 @@ mod test {
|
|||
schema.entid_map.insert(entid, ident.clone());
|
||||
schema.ident_map.insert(ident.clone(), entid);
|
||||
|
||||
schema.schema_map.insert(entid, attribute);
|
||||
schema.attribute_map.insert(entid, attribute);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn validate_schema_map_success() {
|
||||
fn validate_attribute_map_success() {
|
||||
let mut schema = Schema::default();
|
||||
// attribute that is not an index has no uniqueness
|
||||
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bar"), 97, Attribute {
|
||||
|
@ -335,7 +336,7 @@ mod test {
|
|||
component: false,
|
||||
});
|
||||
|
||||
assert!(validate_schema_map(&schema.entid_map, &schema.schema_map).is_ok());
|
||||
assert!(validate_attribute_map(&schema.entid_map, &schema.attribute_map).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -352,7 +353,7 @@ mod test {
|
|||
component: false,
|
||||
});
|
||||
|
||||
let err = validate_schema_map(&schema.entid_map, &schema.schema_map).err();
|
||||
let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err();
|
||||
assert!(err.is_some());
|
||||
|
||||
match err.unwrap() {
|
||||
|
@ -374,7 +375,7 @@ mod test {
|
|||
component: false,
|
||||
});
|
||||
|
||||
let err = validate_schema_map(&schema.entid_map, &schema.schema_map).err();
|
||||
let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err();
|
||||
assert!(err.is_some());
|
||||
|
||||
match err.unwrap() {
|
||||
|
@ -396,7 +397,7 @@ mod test {
|
|||
component: true,
|
||||
});
|
||||
|
||||
let err = validate_schema_map(&schema.entid_map, &schema.schema_map).err();
|
||||
let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err();
|
||||
assert!(err.is_some());
|
||||
|
||||
match err.unwrap() {
|
||||
|
@ -418,7 +419,7 @@ mod test {
|
|||
component: false,
|
||||
});
|
||||
|
||||
let err = validate_schema_map(&schema.entid_map, &schema.schema_map).err();
|
||||
let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err();
|
||||
assert!(err.is_some());
|
||||
|
||||
match err.unwrap() {
|
||||
|
@ -439,7 +440,7 @@ mod test {
|
|||
component: false,
|
||||
});
|
||||
|
||||
let err = validate_schema_map(&schema.entid_map, &schema.schema_map).err();
|
||||
let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err();
|
||||
assert!(err.is_some());
|
||||
|
||||
match err.unwrap() {
|
||||
|
|
18
db/src/tx.rs
18
db/src/tx.rs
|
@ -85,8 +85,10 @@ use mentat_core::{
|
|||
Schema,
|
||||
Utc,
|
||||
attribute,
|
||||
intern_set,
|
||||
};
|
||||
|
||||
use mentat_core::intern_set::InternSet;
|
||||
|
||||
use mentat_tx::entities as entmod;
|
||||
use mentat_tx::entities::{
|
||||
Entity,
|
||||
|
@ -199,13 +201,13 @@ impl<'conn, 'a> Tx<'conn, 'a> {
|
|||
///
|
||||
/// The `Term` instances produce share interned TempId and LookupRef handles, and we return the
|
||||
/// interned handle sets so that consumers can ensure all handles are used appropriately.
|
||||
fn entities_into_terms_with_temp_ids_and_lookup_refs<I>(&self, entities: I) -> Result<(Vec<TermWithTempIdsAndLookupRefs>, intern_set::InternSet<TempId>, intern_set::InternSet<AVPair>)> where I: IntoIterator<Item=Entity> {
|
||||
fn entities_into_terms_with_temp_ids_and_lookup_refs<I>(&self, entities: I) -> Result<(Vec<TermWithTempIdsAndLookupRefs>, InternSet<TempId>, InternSet<AVPair>)> where I: IntoIterator<Item=Entity> {
|
||||
struct InProcess<'a> {
|
||||
partition_map: &'a PartitionMap,
|
||||
schema: &'a Schema,
|
||||
mentat_id_count: i64,
|
||||
temp_ids: intern_set::InternSet<TempId>,
|
||||
lookup_refs: intern_set::InternSet<AVPair>,
|
||||
temp_ids: InternSet<TempId>,
|
||||
lookup_refs: InternSet<AVPair>,
|
||||
}
|
||||
|
||||
impl<'a> InProcess<'a> {
|
||||
|
@ -214,8 +216,8 @@ impl<'conn, 'a> Tx<'conn, 'a> {
|
|||
partition_map,
|
||||
schema,
|
||||
mentat_id_count: 0,
|
||||
temp_ids: intern_set::InternSet::new(),
|
||||
lookup_refs: intern_set::InternSet::new(),
|
||||
temp_ids: InternSet::new(),
|
||||
lookup_refs: InternSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -685,6 +687,8 @@ impl<'conn, 'a> Tx<'conn, 'a> {
|
|||
}
|
||||
|
||||
/// Transact the given `entities` against the given SQLite `conn`, using the given metadata.
|
||||
/// If you want this work to occur inside a SQLite transaction, establish one on the connection
|
||||
/// prior to calling this function.
|
||||
///
|
||||
/// This approach is explained in https://github.com/mozilla/mentat/wiki/Transacting.
|
||||
// TODO: move this to the transactor layer.
|
||||
|
@ -694,8 +698,6 @@ pub fn transact<'conn, 'a, I>(
|
|||
schema_for_mutation: &'a Schema,
|
||||
schema: &'a Schema,
|
||||
entities: I) -> Result<(TxReport, PartitionMap, Option<Schema>)> where I: IntoIterator<Item=Entity> {
|
||||
// Eventually, this function will be responsible for managing a SQLite transaction. For
|
||||
// now, it's just about the tx details.
|
||||
|
||||
let tx_instant = ::now(); // Label the transaction with the timestamp when we first see it: leading edge.
|
||||
let tx_id = partition_map.allocate_entid(":db.part/tx");
|
||||
|
|
|
@ -83,7 +83,6 @@ pub type AVPair = (Entid, TypedValue);
|
|||
pub type AVMap<'a> = HashMap<&'a AVPair, Entid>;
|
||||
|
||||
/// A transaction report summarizes an applied transaction.
|
||||
// TODO: include map of resolved tempids.
|
||||
#[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
||||
pub struct TxReport {
|
||||
/// The transaction ID of the transaction.
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use mentat_core::{
|
||||
HasSchema,
|
||||
Schema,
|
||||
SQLValueType,
|
||||
TypedValue,
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
use mentat_core::{
|
||||
HasSchema,
|
||||
Schema,
|
||||
TypedValue,
|
||||
ValueType,
|
||||
|
|
|
@ -25,6 +25,7 @@ use std::fmt::{
|
|||
use mentat_core::{
|
||||
Attribute,
|
||||
Entid,
|
||||
HasSchema,
|
||||
Schema,
|
||||
TypedValue,
|
||||
ValueType,
|
||||
|
@ -917,7 +918,7 @@ fn associate_ident(schema: &mut Schema, i: NamespacedKeyword, e: Entid) {
|
|||
|
||||
#[cfg(test)]
|
||||
fn add_attribute(schema: &mut Schema, e: Entid, a: Attribute) {
|
||||
schema.schema_map.insert(e, a);
|
||||
schema.attribute_map.insert(e, a);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -79,6 +79,7 @@ mod testing {
|
|||
|
||||
use mentat_core::{
|
||||
Attribute,
|
||||
Schema,
|
||||
TypedValue,
|
||||
ValueType,
|
||||
ValueTypeSet,
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
use mentat_core::{
|
||||
HasSchema,
|
||||
Schema,
|
||||
TypedValue,
|
||||
ValueType,
|
||||
|
|
|
@ -41,7 +41,7 @@ fn associate_ident(schema: &mut Schema, i: NamespacedKeyword, e: Entid) {
|
|||
}
|
||||
|
||||
fn add_attribute(schema: &mut Schema, e: Entid, a: Attribute) {
|
||||
schema.schema_map.insert(e, a);
|
||||
schema.attribute_map.insert(e, a);
|
||||
}
|
||||
|
||||
fn prepopulated_schema() -> Schema {
|
||||
|
|
|
@ -53,7 +53,7 @@ fn associate_ident(schema: &mut Schema, i: NamespacedKeyword, e: Entid) {
|
|||
|
||||
#[cfg(test)]
|
||||
fn add_attribute(schema: &mut Schema, e: Entid, a: Attribute) {
|
||||
schema.schema_map.insert(e, a);
|
||||
schema.attribute_map.insert(e, a);
|
||||
}
|
||||
|
||||
fn prepopulated_schema() -> Schema {
|
||||
|
|
|
@ -48,7 +48,7 @@ fn associate_ident(schema: &mut Schema, i: NamespacedKeyword, e: Entid) {
|
|||
|
||||
#[cfg(test)]
|
||||
fn add_attribute(schema: &mut Schema, e: Entid, a: Attribute) {
|
||||
schema.schema_map.insert(e, a);
|
||||
schema.attribute_map.insert(e, a);
|
||||
}
|
||||
|
||||
fn prepopulated_schema() -> Schema {
|
||||
|
|
|
@ -50,7 +50,7 @@ fn associate_ident(schema: &mut Schema, i: NamespacedKeyword, e: Entid) {
|
|||
}
|
||||
|
||||
fn add_attribute(schema: &mut Schema, e: Entid, a: Attribute) {
|
||||
schema.schema_map.insert(e, a);
|
||||
schema.attribute_map.insert(e, a);
|
||||
}
|
||||
|
||||
fn translate_with_inputs(schema: &Schema, query: &'static str, inputs: QueryInputs) -> SQLQuery {
|
||||
|
|
|
@ -54,6 +54,7 @@ pub use mentat_db::{
|
|||
};
|
||||
|
||||
pub use query::{
|
||||
IntoResult,
|
||||
NamespacedKeyword,
|
||||
PlainSymbol,
|
||||
QueryExplanation,
|
||||
|
|
|
@ -15,6 +15,7 @@ use std::rc::Rc;
|
|||
|
||||
use mentat_core::{
|
||||
Entid,
|
||||
HasSchema,
|
||||
Schema,
|
||||
TypedValue,
|
||||
};
|
||||
|
|
|
@ -22,6 +22,7 @@ use chrono::FixedOffset;
|
|||
|
||||
use mentat_core::{
|
||||
DateTime,
|
||||
HasSchema,
|
||||
TypedValue,
|
||||
ValueType,
|
||||
Utc,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
///! This module defines core types that support the transaction processor.
|
||||
//! This module defines core types that support the transaction processor.
|
||||
|
||||
extern crate edn;
|
||||
|
||||
|
|
Loading…
Reference in a new issue