Pre: Use ValueType rather than Attribute to convert edn::Value to TypedValue.

This is expedient now, but might require work in the future to achieve
better error messages.
This commit is contained in:
Nick Alexander 2017-06-07 13:09:11 -07:00
parent 2650fe163d
commit 05129cefbb
2 changed files with 20 additions and 18 deletions

View file

@ -223,30 +223,32 @@ impl SchemaBuilding for Schema {
pub trait SchemaTypeChecking { pub trait SchemaTypeChecking {
/// Do schema-aware typechecking and coercion. /// Do schema-aware typechecking and coercion.
/// ///
/// Either assert that the given value is in the attribute's value set, or (in limited cases) /// Either assert that the given value is in the value type's value set, or (in limited cases)
/// coerce the given value into the attribute's value set. /// coerce the given value into the value type's value set.
fn to_typed_value(&self, value: &edn::Value, attribute: &Attribute) -> Result<TypedValue>; fn to_typed_value(&self, value: &edn::Value, value_type: ValueType) -> Result<TypedValue>;
} }
impl SchemaTypeChecking for Schema { impl SchemaTypeChecking for Schema {
fn to_typed_value(&self, value: &edn::Value, attribute: &Attribute) -> Result<TypedValue> { fn to_typed_value(&self, value: &edn::Value, value_type: ValueType) -> Result<TypedValue> {
// TODO: encapsulate entid-ident-attribute for better error messages. // TODO: encapsulate entid-ident-attribute for better error messages, perhaps by including
// the attribute (rather than just the attribute's value type) into this function or a
// wrapper function.
match TypedValue::from_edn_value(value) { match TypedValue::from_edn_value(value) {
// We don't recognize this EDN at all. Get out! // We don't recognize this EDN at all. Get out!
None => bail!(ErrorKind::BadEDNValuePair(value.clone(), attribute.value_type.clone())), None => bail!(ErrorKind::BadEDNValuePair(value.clone(), value_type)),
Some(typed_value) => match (&attribute.value_type, typed_value) { Some(typed_value) => match (value_type, typed_value) {
// Most types don't coerce at all. // Most types don't coerce at all.
(&ValueType::Boolean, tv @ TypedValue::Boolean(_)) => Ok(tv), (ValueType::Boolean, tv @ TypedValue::Boolean(_)) => Ok(tv),
(&ValueType::Long, tv @ TypedValue::Long(_)) => Ok(tv), (ValueType::Long, tv @ TypedValue::Long(_)) => Ok(tv),
(&ValueType::Double, tv @ TypedValue::Double(_)) => Ok(tv), (ValueType::Double, tv @ TypedValue::Double(_)) => Ok(tv),
(&ValueType::String, tv @ TypedValue::String(_)) => Ok(tv), (ValueType::String, tv @ TypedValue::String(_)) => Ok(tv),
(&ValueType::Uuid, tv @ TypedValue::Uuid(_)) => Ok(tv), (ValueType::Uuid, tv @ TypedValue::Uuid(_)) => Ok(tv),
(&ValueType::Keyword, tv @ TypedValue::Keyword(_)) => Ok(tv), (ValueType::Keyword, tv @ TypedValue::Keyword(_)) => Ok(tv),
// Ref coerces a little: we interpret some things depending on the schema as a Ref. // Ref coerces a little: we interpret some things depending on the schema as a Ref.
(&ValueType::Ref, TypedValue::Long(x)) => Ok(TypedValue::Ref(x)), (ValueType::Ref, TypedValue::Long(x)) => Ok(TypedValue::Ref(x)),
(&ValueType::Ref, TypedValue::Keyword(ref x)) => self.require_entid(&x).map(|entid| TypedValue::Ref(entid)), (ValueType::Ref, TypedValue::Keyword(ref x)) => self.require_entid(&x).map(|entid| TypedValue::Ref(entid)),
// Otherwise, we have a type mismatch. // Otherwise, we have a type mismatch.
(value_type, _) => bail!(ErrorKind::BadEDNValuePair(value.clone(), value_type.clone())), (value_type, _) => bail!(ErrorKind::BadEDNValuePair(value.clone(), value_type)),
} }
} }
} }

View file

@ -205,7 +205,7 @@ impl<'conn, 'a> Tx<'conn, 'a> {
bail!(ErrorKind::NotYetImplemented(format!("Cannot resolve (lookup-ref {} {}) with attribute that is not :db/unique", lr_a, lookup_ref.v))) bail!(ErrorKind::NotYetImplemented(format!("Cannot resolve (lookup-ref {} {}) with attribute that is not :db/unique", lr_a, lookup_ref.v)))
} }
let lr_typed_value: TypedValue = self.schema.to_typed_value(&lookup_ref.v, &lr_attribute)?; let lr_typed_value: TypedValue = self.schema.to_typed_value(&lookup_ref.v, lr_attribute.value_type)?;
Ok(lookup_refs.intern((lr_a, lr_typed_value))) Ok(lookup_refs.intern((lr_a, lr_typed_value)))
}; };
@ -260,7 +260,7 @@ impl<'conn, 'a> Tx<'conn, 'a> {
// Here is where we do schema-aware typechecking: we either assert that // Here is where we do schema-aware typechecking: we either assert that
// the given value is in the attribute's value set, or (in limited // the given value is in the attribute's value set, or (in limited
// cases) coerce the value into the attribute's value set. // cases) coerce the value into the attribute's value set.
let typed_value: TypedValue = self.schema.to_typed_value(&v.without_spans(), &attribute)?; let typed_value: TypedValue = self.schema.to_typed_value(&v.without_spans(), attribute.value_type)?;
Either::Left(typed_value) Either::Left(typed_value)
} }
}, },