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:
parent
2650fe163d
commit
05129cefbb
2 changed files with 20 additions and 18 deletions
|
@ -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)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue