Part 5: Make existing TermBuilder
actually build Entity
instances.
There are a few tricky details to call out here. The first is the `TransactableValueMarker` trait. This is strictly a marker (like `Sized`, for example) to give some control over what types can be used as value types in `Entity` instances. This expression is needed due to the network of `Into` and `From` relations between the parts of valid `Entity` instances. This allows to drop the `IntoThing` work-around trait and use the established patterns. (Observe that `KnownEntid` makes this a little harder, due to the cross-crate consistency restrictions.) The second is that we can get rid `{add,retract}_kw`, since the network of relations expresses the coercions directly. The third is that this commit doesn't change the name `TermBuilder`, even though it is now building `Entity` instances. This is because there's _already_ an `EntityBuilder` which fixes the `EntityPlace`. It's not clear whether the existing entity building interface should be removed or whether both should be renamed. That can be follow-up.
This commit is contained in:
parent
76507623ac
commit
1cb1847aa6
7 changed files with 246 additions and 218 deletions
|
@ -47,6 +47,14 @@ use ::edn::{
|
||||||
ValueRc,
|
ValueRc,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use ::edn::entities::{
|
||||||
|
AttributePlace,
|
||||||
|
EntidOrIdent,
|
||||||
|
EntityPlace,
|
||||||
|
ValuePlace,
|
||||||
|
TransactableValueMarker,
|
||||||
|
};
|
||||||
|
|
||||||
use values;
|
use values;
|
||||||
|
|
||||||
/// Represents one entid in the entid space.
|
/// Represents one entid in the entid space.
|
||||||
|
@ -73,6 +81,24 @@ impl From<KnownEntid> for TypedValue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V: TransactableValueMarker> Into<EntityPlace<V>> for KnownEntid {
|
||||||
|
fn into(self) -> EntityPlace<V> {
|
||||||
|
EntityPlace::Entid(EntidOrIdent::Entid(self.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<AttributePlace> for KnownEntid {
|
||||||
|
fn into(self) -> AttributePlace {
|
||||||
|
AttributePlace::Entid(EntidOrIdent::Entid(self.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: TransactableValueMarker> Into<ValuePlace<V>> for KnownEntid {
|
||||||
|
fn into(self) -> ValuePlace<V> {
|
||||||
|
ValuePlace::Entid(EntidOrIdent::Entid(self.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The attribute of each Mentat assertion has a :db/valueType constraining the value to a
|
/// The attribute of each Mentat assertion has a :db/valueType constraining the value to a
|
||||||
/// particular set. Mentat recognizes the following :db/valueType values.
|
/// particular set. Mentat recognizes the following :db/valueType values.
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
||||||
|
@ -215,6 +241,9 @@ pub enum TypedValue {
|
||||||
Uuid(Uuid), // It's only 128 bits, so this should be acceptable to clone.
|
Uuid(Uuid), // It's only 128 bits, so this should be acceptable to clone.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `TypedValue` is the value type for programmatic use in transaction builders.
|
||||||
|
impl TransactableValueMarker for TypedValue {}
|
||||||
|
|
||||||
/// The values bound in a query specification can be:
|
/// The values bound in a query specification can be:
|
||||||
///
|
///
|
||||||
/// * Vecs of structured values, for multi-valued component attributes or nested expressions.
|
/// * Vecs of structured values, for multi-valued component attributes or nested expressions.
|
||||||
|
|
|
@ -22,6 +22,20 @@ use symbols::{
|
||||||
PlainSymbol,
|
PlainSymbol,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use types::{
|
||||||
|
ValueAndSpan,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// `EntityPlace` and `ValuePlace` embed values, either directly (i.e., `ValuePlace::Atom`) or
|
||||||
|
/// indirectly (i.e., `EntityPlace::LookupRef`). In order to maintain the graph of `Into` and
|
||||||
|
/// `From` relations, we need to ensure that `{Value,Entity}Place` can't match as a potential value.
|
||||||
|
/// (If it does, the `impl Into<T> for T` default conflicts.) This marker trait allows to mark
|
||||||
|
/// acceptable values, thereby removing `{Entity,Value}Place` from consideration.
|
||||||
|
pub trait TransactableValueMarker {}
|
||||||
|
|
||||||
|
/// `ValueAndSpan` is the value type coming out of the entity parser.
|
||||||
|
impl TransactableValueMarker for ValueAndSpan {}
|
||||||
|
|
||||||
/// A tempid, either an external tempid given in a transaction (usually as an `Value::Text`),
|
/// A tempid, either an external tempid given in a transaction (usually as an `Value::Text`),
|
||||||
/// or an internal tempid allocated by Mentat itself.
|
/// or an internal tempid allocated by Mentat itself.
|
||||||
#[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
#[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
||||||
|
@ -54,6 +68,18 @@ pub enum EntidOrIdent {
|
||||||
Ident(Keyword),
|
Ident(Keyword),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<i64> for EntidOrIdent {
|
||||||
|
fn from(v: i64) -> Self {
|
||||||
|
EntidOrIdent::Entid(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Keyword> for EntidOrIdent {
|
||||||
|
fn from(v: Keyword) -> Self {
|
||||||
|
EntidOrIdent::Ident(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl EntidOrIdent {
|
impl EntidOrIdent {
|
||||||
pub fn unreversed(&self) -> Option<EntidOrIdent> {
|
pub fn unreversed(&self) -> Option<EntidOrIdent> {
|
||||||
match self {
|
match self {
|
||||||
|
@ -105,6 +131,54 @@ pub enum ValuePlace<V> {
|
||||||
MapNotation(MapNotation<V>),
|
MapNotation(MapNotation<V>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V: TransactableValueMarker> From<EntidOrIdent> for ValuePlace<V> {
|
||||||
|
fn from(v: EntidOrIdent) -> Self {
|
||||||
|
ValuePlace::Entid(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: TransactableValueMarker> From<TempId> for ValuePlace<V> {
|
||||||
|
fn from(v: TempId) -> Self {
|
||||||
|
ValuePlace::TempId(v.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: TransactableValueMarker> From<ValueRc<TempId>> for ValuePlace<V> {
|
||||||
|
fn from(v: ValueRc<TempId>) -> Self {
|
||||||
|
ValuePlace::TempId(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: TransactableValueMarker> From<LookupRef<V>> for ValuePlace<V> {
|
||||||
|
fn from(v: LookupRef<V>) -> Self {
|
||||||
|
ValuePlace::LookupRef(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: TransactableValueMarker> From<TxFunction> for ValuePlace<V> {
|
||||||
|
fn from(v: TxFunction) -> Self {
|
||||||
|
ValuePlace::TxFunction(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: TransactableValueMarker> From<Vec<ValuePlace<V>>> for ValuePlace<V> {
|
||||||
|
fn from(v: Vec<ValuePlace<V>>) -> Self {
|
||||||
|
ValuePlace::Vector(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: TransactableValueMarker> From<V> for ValuePlace<V> {
|
||||||
|
fn from(v: V) -> Self {
|
||||||
|
ValuePlace::Atom(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: TransactableValueMarker> From<MapNotation<V>> for ValuePlace<V> {
|
||||||
|
fn from(v: MapNotation<V>) -> Self {
|
||||||
|
ValuePlace::MapNotation(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
#[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
||||||
pub enum EntityPlace<V> {
|
pub enum EntityPlace<V> {
|
||||||
Entid(EntidOrIdent),
|
Entid(EntidOrIdent),
|
||||||
|
@ -113,11 +187,47 @@ pub enum EntityPlace<V> {
|
||||||
TxFunction(TxFunction),
|
TxFunction(TxFunction),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V, E: Into<EntidOrIdent>> From<E> for EntityPlace<V> {
|
||||||
|
fn from(v: E) -> Self {
|
||||||
|
EntityPlace::Entid(v.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: TransactableValueMarker> From<TempId> for EntityPlace<V> {
|
||||||
|
fn from(v: TempId) -> Self {
|
||||||
|
EntityPlace::TempId(v.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: TransactableValueMarker> From<ValueRc<TempId>> for EntityPlace<V> {
|
||||||
|
fn from(v: ValueRc<TempId>) -> Self {
|
||||||
|
EntityPlace::TempId(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: TransactableValueMarker> From<LookupRef<V>> for EntityPlace<V> {
|
||||||
|
fn from(v: LookupRef<V>) -> Self {
|
||||||
|
EntityPlace::LookupRef(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: TransactableValueMarker> From<TxFunction> for EntityPlace<V> {
|
||||||
|
fn from(v: TxFunction) -> Self {
|
||||||
|
EntityPlace::TxFunction(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
#[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
||||||
pub enum AttributePlace {
|
pub enum AttributePlace {
|
||||||
Entid(EntidOrIdent),
|
Entid(EntidOrIdent),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<A: Into<EntidOrIdent>> From<A> for AttributePlace {
|
||||||
|
fn from(v: A) -> Self {
|
||||||
|
AttributePlace::Entid(v.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
||||||
pub enum OpType {
|
pub enum OpType {
|
||||||
Add,
|
Add,
|
||||||
|
|
|
@ -120,7 +120,6 @@ pub use mentat::entity_builder::{
|
||||||
BuildTerms,
|
BuildTerms,
|
||||||
EntityBuilder,
|
EntityBuilder,
|
||||||
InProgressBuilder,
|
InProgressBuilder,
|
||||||
IntoThing,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod android;
|
pub mod android;
|
||||||
|
@ -339,7 +338,7 @@ pub unsafe extern "C" fn in_progress_entity_builder_from_temp_id<'m>(in_progress
|
||||||
pub unsafe extern "C" fn in_progress_entity_builder_from_entid<'m>(in_progress: *mut InProgress<'m, 'm>, entid: c_longlong) -> *mut EntityBuilder<InProgressBuilder> {
|
pub unsafe extern "C" fn in_progress_entity_builder_from_entid<'m>(in_progress: *mut InProgress<'m, 'm>, entid: c_longlong) -> *mut EntityBuilder<InProgressBuilder> {
|
||||||
assert_not_null!(in_progress);
|
assert_not_null!(in_progress);
|
||||||
let in_progress = Box::from_raw(in_progress);
|
let in_progress = Box::from_raw(in_progress);
|
||||||
Box::into_raw(Box::new(in_progress.builder().describe(&KnownEntid(entid))))
|
Box::into_raw(Box::new(in_progress.builder().describe(KnownEntid(entid))))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Starts a new transaction and creates a builder using the transaction
|
/// Starts a new transaction and creates a builder using the transaction
|
||||||
|
@ -392,7 +391,7 @@ pub unsafe extern "C" fn store_entity_builder_from_entid<'a, 'c>(store: *mut Sto
|
||||||
assert_not_null!(store);
|
assert_not_null!(store);
|
||||||
let store = &mut *store;
|
let store = &mut *store;
|
||||||
let result = store.begin_transaction().and_then(|in_progress| {
|
let result = store.begin_transaction().and_then(|in_progress| {
|
||||||
Ok(in_progress.builder().describe(&KnownEntid(entid)))
|
Ok(in_progress.builder().describe(KnownEntid(entid)))
|
||||||
});
|
});
|
||||||
translate_result(result, error)
|
translate_result(result, error)
|
||||||
}
|
}
|
||||||
|
@ -418,7 +417,7 @@ pub unsafe extern "C" fn in_progress_builder_add_string<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = c_char_to_string(value).into();
|
let value: TypedValue = c_char_to_string(value).into();
|
||||||
translate_void_result(builder.add_kw(KnownEntid(entid), &kw, value), error);
|
translate_void_result(builder.add(KnownEntid(entid), kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
||||||
|
@ -441,7 +440,7 @@ pub unsafe extern "C" fn in_progress_builder_add_long<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = TypedValue::Long(value);
|
let value: TypedValue = TypedValue::Long(value);
|
||||||
translate_void_result(builder.add_kw(KnownEntid(entid), &kw, value), error);
|
translate_void_result(builder.add(KnownEntid(entid), kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
||||||
|
@ -465,7 +464,7 @@ pub unsafe extern "C" fn in_progress_builder_add_ref<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = TypedValue::Ref(value);
|
let value: TypedValue = TypedValue::Ref(value);
|
||||||
translate_void_result(builder.add_kw(KnownEntid(entid), &kw, value), error);
|
translate_void_result(builder.add(KnownEntid(entid), kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
||||||
|
@ -490,7 +489,7 @@ pub unsafe extern "C" fn in_progress_builder_add_keyword<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = kw_from_string(c_char_to_string(value)).into();
|
let value: TypedValue = kw_from_string(c_char_to_string(value)).into();
|
||||||
translate_void_result(builder.add_kw(KnownEntid(entid), &kw, value), error);
|
translate_void_result(builder.add(KnownEntid(entid), kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
||||||
|
@ -514,7 +513,7 @@ pub unsafe extern "C" fn in_progress_builder_add_boolean<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = value.into();
|
let value: TypedValue = value.into();
|
||||||
translate_void_result(builder.add_kw(KnownEntid(entid), &kw, value), error);
|
translate_void_result(builder.add(KnownEntid(entid), kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
||||||
|
@ -538,7 +537,7 @@ pub unsafe extern "C" fn in_progress_builder_add_double<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = value.into();
|
let value: TypedValue = value.into();
|
||||||
translate_void_result(builder.add_kw(KnownEntid(entid), &kw, value), error);
|
translate_void_result(builder.add(KnownEntid(entid), kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
||||||
|
@ -562,7 +561,7 @@ pub unsafe extern "C" fn in_progress_builder_add_timestamp<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = TypedValue::instant(value);
|
let value: TypedValue = TypedValue::instant(value);
|
||||||
translate_void_result(builder.add_kw(KnownEntid(entid), &kw, value), error);
|
translate_void_result(builder.add(KnownEntid(entid), kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
||||||
|
@ -588,7 +587,7 @@ pub unsafe extern "C" fn in_progress_builder_add_uuid<'a, 'c>(
|
||||||
let value = &*value;
|
let value = &*value;
|
||||||
let value = Uuid::from_bytes(value).expect("valid uuid");
|
let value = Uuid::from_bytes(value).expect("valid uuid");
|
||||||
let value: TypedValue = value.into();
|
let value: TypedValue = value.into();
|
||||||
translate_void_result(builder.add_kw(KnownEntid(entid), &kw, value), error);
|
translate_void_result(builder.add(KnownEntid(entid), kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
||||||
|
@ -612,7 +611,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_string<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = c_char_to_string(value).into();
|
let value: TypedValue = c_char_to_string(value).into();
|
||||||
translate_void_result(builder.retract_kw(KnownEntid(entid), &kw, value), error);
|
translate_void_result(builder.retract(KnownEntid(entid), kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
||||||
|
@ -636,7 +635,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_long<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = TypedValue::Long(value);
|
let value: TypedValue = TypedValue::Long(value);
|
||||||
translate_void_result(builder.retract_kw(KnownEntid(entid), &kw, value), error);
|
translate_void_result(builder.retract(KnownEntid(entid), kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
||||||
|
@ -660,7 +659,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_ref<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = TypedValue::Ref(value);
|
let value: TypedValue = TypedValue::Ref(value);
|
||||||
translate_void_result(builder.retract_kw(KnownEntid(entid), &kw, value), error);
|
translate_void_result(builder.retract(KnownEntid(entid), kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -685,7 +684,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_keyword<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = kw_from_string(c_char_to_string(value)).into();
|
let value: TypedValue = kw_from_string(c_char_to_string(value)).into();
|
||||||
translate_void_result(builder.retract_kw(KnownEntid(entid), &kw, value), error);
|
translate_void_result(builder.retract(KnownEntid(entid), kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
||||||
|
@ -709,7 +708,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_boolean<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = value.into();
|
let value: TypedValue = value.into();
|
||||||
translate_void_result(builder.retract_kw(KnownEntid(entid), &kw, value), error);
|
translate_void_result(builder.retract(KnownEntid(entid), kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
||||||
|
@ -733,7 +732,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_double<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = value.into();
|
let value: TypedValue = value.into();
|
||||||
translate_void_result(builder.retract_kw(KnownEntid(entid), &kw, value), error);
|
translate_void_result(builder.retract(KnownEntid(entid), kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
||||||
|
@ -757,7 +756,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_timestamp<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = TypedValue::instant(value);
|
let value: TypedValue = TypedValue::instant(value);
|
||||||
translate_void_result(builder.retract_kw(KnownEntid(entid), &kw, value), error);
|
translate_void_result(builder.retract(KnownEntid(entid), kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
||||||
|
@ -785,7 +784,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_uuid<'a, 'c>(
|
||||||
let value = &*value;
|
let value = &*value;
|
||||||
let value = Uuid::from_bytes(value).expect("valid uuid");
|
let value = Uuid::from_bytes(value).expect("valid uuid");
|
||||||
let value: TypedValue = value.into();
|
let value: TypedValue = value.into();
|
||||||
translate_void_result(builder.retract_kw(KnownEntid(entid), &kw, value), error);
|
translate_void_result(builder.retract(KnownEntid(entid), kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transacts and commits all the assertions and retractions that have been performed
|
/// Transacts and commits all the assertions and retractions that have been performed
|
||||||
|
@ -842,7 +841,7 @@ pub unsafe extern "C" fn entity_builder_add_string<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = c_char_to_string(value).into();
|
let value: TypedValue = c_char_to_string(value).into();
|
||||||
translate_void_result(builder.add_kw(&kw, value), error);
|
translate_void_result(builder.add(kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
||||||
|
@ -865,7 +864,7 @@ pub unsafe extern "C" fn entity_builder_add_long<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = TypedValue::Long(value);
|
let value: TypedValue = TypedValue::Long(value);
|
||||||
translate_void_result(builder.add_kw(&kw, value), error);
|
translate_void_result(builder.add(kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
||||||
|
@ -888,7 +887,7 @@ pub unsafe extern "C" fn entity_builder_add_ref<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = TypedValue::Ref(value);
|
let value: TypedValue = TypedValue::Ref(value);
|
||||||
translate_void_result(builder.add_kw(&kw, value), error);
|
translate_void_result(builder.add(kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
||||||
|
@ -911,7 +910,7 @@ pub unsafe extern "C" fn entity_builder_add_keyword<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = kw_from_string(c_char_to_string(value)).into();
|
let value: TypedValue = kw_from_string(c_char_to_string(value)).into();
|
||||||
translate_void_result(builder.add_kw(&kw, value), error);
|
translate_void_result(builder.add(kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
||||||
|
@ -934,7 +933,7 @@ pub unsafe extern "C" fn entity_builder_add_boolean<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = value.into();
|
let value: TypedValue = value.into();
|
||||||
translate_void_result(builder.add_kw(&kw, value), error);
|
translate_void_result(builder.add(kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
||||||
|
@ -957,7 +956,7 @@ pub unsafe extern "C" fn entity_builder_add_double<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = value.into();
|
let value: TypedValue = value.into();
|
||||||
translate_void_result(builder.add_kw(&kw, value), error);
|
translate_void_result(builder.add(kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
||||||
|
@ -980,7 +979,7 @@ pub unsafe extern "C" fn entity_builder_add_timestamp<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = TypedValue::instant(value);
|
let value: TypedValue = TypedValue::instant(value);
|
||||||
translate_void_result(builder.add_kw(&kw, value), error);
|
translate_void_result(builder.add(kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
/// Uses `builder` to assert `value` for `kw` on entity `entid`.
|
||||||
|
@ -1005,7 +1004,7 @@ pub unsafe extern "C" fn entity_builder_add_uuid<'a, 'c>(
|
||||||
let value = &*value;
|
let value = &*value;
|
||||||
let value = Uuid::from_bytes(value).expect("valid uuid");
|
let value = Uuid::from_bytes(value).expect("valid uuid");
|
||||||
let value: TypedValue = value.into();
|
let value: TypedValue = value.into();
|
||||||
translate_void_result(builder.add_kw(&kw, value), error);
|
translate_void_result(builder.add(kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
||||||
|
@ -1028,7 +1027,7 @@ pub unsafe extern "C" fn entity_builder_retract_string<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = c_char_to_string(value).into();
|
let value: TypedValue = c_char_to_string(value).into();
|
||||||
translate_void_result(builder.retract_kw(&kw, value), error);
|
translate_void_result(builder.retract(kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
||||||
|
@ -1051,7 +1050,7 @@ pub unsafe extern "C" fn entity_builder_retract_long<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = TypedValue::Long(value);
|
let value: TypedValue = TypedValue::Long(value);
|
||||||
translate_void_result(builder.retract_kw(&kw, value), error);
|
translate_void_result(builder.retract(kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
||||||
|
@ -1074,7 +1073,7 @@ pub unsafe extern "C" fn entity_builder_retract_ref<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = TypedValue::Ref(value);
|
let value: TypedValue = TypedValue::Ref(value);
|
||||||
translate_void_result(builder.retract_kw(&kw, value), error);
|
translate_void_result(builder.retract(kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
||||||
|
@ -1097,7 +1096,7 @@ pub unsafe extern "C" fn entity_builder_retract_keyword<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = kw_from_string(c_char_to_string(value)).into();
|
let value: TypedValue = kw_from_string(c_char_to_string(value)).into();
|
||||||
translate_void_result(builder.retract_kw(&kw, value), error);
|
translate_void_result(builder.retract(kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
||||||
|
@ -1120,7 +1119,7 @@ pub unsafe extern "C" fn entity_builder_retract_boolean<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = value.into();
|
let value: TypedValue = value.into();
|
||||||
translate_void_result(builder.retract_kw(&kw, value), error);
|
translate_void_result(builder.retract(kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
||||||
|
@ -1143,7 +1142,7 @@ pub unsafe extern "C" fn entity_builder_retract_double<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = value.into();
|
let value: TypedValue = value.into();
|
||||||
translate_void_result(builder.retract_kw(&kw, value), error);
|
translate_void_result(builder.retract(kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
||||||
|
@ -1166,7 +1165,7 @@ pub unsafe extern "C" fn entity_builder_retract_timestamp<'a, 'c>(
|
||||||
let builder = &mut *builder;
|
let builder = &mut *builder;
|
||||||
let kw = kw_from_string(c_char_to_string(kw));
|
let kw = kw_from_string(c_char_to_string(kw));
|
||||||
let value: TypedValue = TypedValue::instant(value);
|
let value: TypedValue = TypedValue::instant(value);
|
||||||
translate_void_result(builder.retract_kw(&kw, value), error);
|
translate_void_result(builder.retract(kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
/// Uses `builder` to retract `value` for `kw` on entity `entid`.
|
||||||
|
@ -1192,7 +1191,7 @@ pub unsafe extern "C" fn entity_builder_retract_uuid<'a, 'c>(
|
||||||
let value = &*value;
|
let value = &*value;
|
||||||
let value = Uuid::from_bytes(value).expect("valid uuid");
|
let value = Uuid::from_bytes(value).expect("valid uuid");
|
||||||
let value: TypedValue = value.into();
|
let value: TypedValue = value.into();
|
||||||
translate_void_result(builder.retract_kw(&kw, value), error);
|
translate_void_result(builder.retract(kw, value), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transacts all the assertions and retractions that have been performed
|
/// Transacts all the assertions and retractions that have been performed
|
||||||
|
|
|
@ -402,8 +402,8 @@ impl<'a, 'c> InProgress<'a, 'c> {
|
||||||
/// This exists so you can make your own.
|
/// This exists so you can make your own.
|
||||||
pub fn transact_builder(&mut self, builder: TermBuilder) -> Result<TxReport> {
|
pub fn transact_builder(&mut self, builder: TermBuilder) -> Result<TxReport> {
|
||||||
builder.build()
|
builder.build()
|
||||||
.and_then(|(terms, tempid_set)| {
|
.and_then(|(terms, _tempid_set)| {
|
||||||
self.transact_terms(terms, tempid_set)
|
self.transact_entities(terms)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,73 +50,65 @@
|
||||||
//
|
//
|
||||||
// The second is to expose a declarative, programmatic builder pattern for constructing entities.
|
// The second is to expose a declarative, programmatic builder pattern for constructing entities.
|
||||||
//
|
//
|
||||||
// We probably need both, but this file provides the latter. Unfortunately, Entity -- the input to
|
// We probably need both, but this file provides the latter.
|
||||||
// the transactor -- is intimately tied to EDN and to spanned values.
|
|
||||||
|
|
||||||
use edn::{
|
use edn::{
|
||||||
InternSet,
|
InternSet,
|
||||||
|
ValueRc,
|
||||||
};
|
};
|
||||||
use edn::entities::{
|
use edn::entities::{
|
||||||
|
AttributePlace,
|
||||||
|
Entity,
|
||||||
|
EntityPlace,
|
||||||
OpType,
|
OpType,
|
||||||
TempId,
|
TempId,
|
||||||
|
ValuePlace,
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_core::{
|
use mentat_core::{
|
||||||
HasSchema,
|
|
||||||
KnownEntid,
|
|
||||||
Keyword,
|
|
||||||
TypedValue,
|
TypedValue,
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_core::util::Either;
|
|
||||||
|
|
||||||
use mentat_db::{
|
use mentat_db::{
|
||||||
TxReport,
|
TxReport,
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_db::internal_types::{
|
|
||||||
KnownEntidOr,
|
|
||||||
TempIdHandle,
|
|
||||||
Term,
|
|
||||||
TermWithTempIds,
|
|
||||||
TypedValueOr,
|
|
||||||
};
|
|
||||||
|
|
||||||
use conn::{
|
use conn::{
|
||||||
InProgress,
|
InProgress,
|
||||||
};
|
};
|
||||||
|
|
||||||
use errors::{
|
use errors::{
|
||||||
MentatError,
|
|
||||||
Result,
|
Result,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type Terms = (Vec<TermWithTempIds>, InternSet<TempId>);
|
pub type Terms = (Vec<Entity<TypedValue>>, InternSet<TempId>);
|
||||||
|
|
||||||
pub struct TermBuilder {
|
pub struct TermBuilder {
|
||||||
tempids: InternSet<TempId>,
|
tempids: InternSet<TempId>,
|
||||||
terms: Vec<TermWithTempIds>,
|
terms: Vec<Entity<TypedValue>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EntityBuilder<T: BuildTerms + Sized> {
|
pub struct EntityBuilder<T: BuildTerms + Sized> {
|
||||||
builder: T,
|
builder: T,
|
||||||
entity: KnownEntidOr<TempIdHandle>,
|
entity: EntityPlace<TypedValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait BuildTerms where Self: Sized {
|
pub trait BuildTerms where Self: Sized {
|
||||||
fn named_tempid(&mut self, name: String) -> TempIdHandle;
|
fn named_tempid(&mut self, name: String) -> ValueRc<TempId>;
|
||||||
fn describe_tempid(self, name: &str) -> EntityBuilder<Self>;
|
fn describe_tempid(self, name: &str) -> EntityBuilder<Self>;
|
||||||
fn describe<E>(self, entity: E) -> EntityBuilder<Self> where E: IntoThing<KnownEntidOr<TempIdHandle>>;
|
fn describe<E>(self, entity: E) -> EntityBuilder<Self> where E: Into<EntityPlace<TypedValue>>;
|
||||||
fn add<E, V>(&mut self, e: E, a: KnownEntid, v: V) -> Result<()>
|
fn add<E, A, V>(&mut self, e: E, a: A, v: V) -> Result<()>
|
||||||
where E: IntoThing<KnownEntidOr<TempIdHandle>>,
|
where E: Into<EntityPlace<TypedValue>>,
|
||||||
V: IntoThing<TypedValueOr<TempIdHandle>>;
|
A: Into<AttributePlace>,
|
||||||
fn retract<E, V>(&mut self, e: E, a: KnownEntid, v: V) -> Result<()>
|
V: Into<ValuePlace<TypedValue>>;
|
||||||
where E: IntoThing<KnownEntidOr<TempIdHandle>>,
|
fn retract<E, A, V>(&mut self, e: E, a: A, v: V) -> Result<()>
|
||||||
V: IntoThing<TypedValueOr<TempIdHandle>>;
|
where E: Into<EntityPlace<TypedValue>>,
|
||||||
|
A: Into<AttributePlace>,
|
||||||
|
V: Into<ValuePlace<TypedValue>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BuildTerms for TermBuilder {
|
impl BuildTerms for TermBuilder {
|
||||||
fn named_tempid(&mut self, name: String) -> TempIdHandle {
|
fn named_tempid(&mut self, name: String) -> ValueRc<TempId> {
|
||||||
self.tempids.intern(TempId::External(name))
|
self.tempids.intern(TempId::External(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,28 +117,26 @@ impl BuildTerms for TermBuilder {
|
||||||
self.describe(e)
|
self.describe(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn describe<E>(self, entity: E) -> EntityBuilder<Self> where E: IntoThing<KnownEntidOr<TempIdHandle>> {
|
fn describe<E>(self, entity: E) -> EntityBuilder<Self> where E: Into<EntityPlace<TypedValue>> {
|
||||||
EntityBuilder {
|
EntityBuilder {
|
||||||
builder: self,
|
builder: self,
|
||||||
entity: entity.into_thing(),
|
entity: entity.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add<E, V>(&mut self, e: E, a: KnownEntid, v: V) -> Result<()>
|
fn add<E, A, V>(&mut self, e: E, a: A, v: V) -> Result<()>
|
||||||
where E: IntoThing<KnownEntidOr<TempIdHandle>>,
|
where E: Into<EntityPlace<TypedValue>>,
|
||||||
V: IntoThing<TypedValueOr<TempIdHandle>> {
|
A: Into<AttributePlace>,
|
||||||
let e = e.into_thing();
|
V: Into<ValuePlace<TypedValue>> {
|
||||||
let v = v.into_thing();
|
self.terms.push(Entity::AddOrRetract { op: OpType::Add, e: e.into(), a: a.into(), v: v.into() });
|
||||||
self.terms.push(Term::AddOrRetract(OpType::Add, e, a.into(), v));
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn retract<E, V>(&mut self, e: E, a: KnownEntid, v: V) -> Result<()>
|
fn retract<E, A, V>(&mut self, e: E, a: A, v: V) -> Result<()>
|
||||||
where E: IntoThing<KnownEntidOr<TempIdHandle>>,
|
where E: Into<EntityPlace<TypedValue>>,
|
||||||
V: IntoThing<TypedValueOr<TempIdHandle>> {
|
A: Into<AttributePlace>,
|
||||||
let e = e.into_thing();
|
V: Into<ValuePlace<TypedValue>> {
|
||||||
let v = v.into_thing();
|
self.terms.push(Entity::AddOrRetract { op: OpType::Retract, e: e.into(), a: a.into(), v: v.into() });
|
||||||
self.terms.push(Term::AddOrRetract(OpType::Retract, e, a.into(), v));
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,23 +158,25 @@ impl TermBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn numbered_tempid(&mut self, id: i64) -> TempIdHandle {
|
pub fn numbered_tempid(&mut self, id: i64) -> ValueRc<TempId> {
|
||||||
self.tempids.intern(TempId::Internal(id))
|
self.tempids.intern(TempId::Internal(id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> EntityBuilder<T> where T: BuildTerms {
|
impl<T> EntityBuilder<T> where T: BuildTerms {
|
||||||
pub fn finish(self) -> (T, KnownEntidOr<TempIdHandle>) {
|
pub fn finish(self) -> (T, EntityPlace<TypedValue>) {
|
||||||
(self.builder, self.entity)
|
(self.builder, self.entity)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add<V>(&mut self, a: KnownEntid, v: V) -> Result<()>
|
pub fn add<A, V>(&mut self, a: A, v: V) -> Result<()>
|
||||||
where V: IntoThing<TypedValueOr<TempIdHandle>> {
|
where A: Into<AttributePlace>,
|
||||||
|
V: Into<ValuePlace<TypedValue>> {
|
||||||
self.builder.add(self.entity.clone(), a, v)
|
self.builder.add(self.entity.clone(), a, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn retract<V>(&mut self, a: KnownEntid, v: V) -> Result<()>
|
pub fn retract<A, V>(&mut self, a: A, v: V) -> Result<()>
|
||||||
where V: IntoThing<TypedValueOr<TempIdHandle>> {
|
where A: Into<AttributePlace>,
|
||||||
|
V: Into<ValuePlace<TypedValue>> {
|
||||||
self.builder.retract(self.entity.clone(), a, v)
|
self.builder.retract(self.entity.clone(), a, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,8 +201,8 @@ impl<'a, 'c> InProgressBuilder<'a, 'c> {
|
||||||
let mut in_progress = self.in_progress;
|
let mut in_progress = self.in_progress;
|
||||||
let result = self.builder
|
let result = self.builder
|
||||||
.build()
|
.build()
|
||||||
.and_then(|(terms, tempid_set)| {
|
.and_then(|(terms, _tempid_set)| {
|
||||||
in_progress.transact_terms(terms, tempid_set)
|
in_progress.transact_entities(terms)
|
||||||
});
|
});
|
||||||
(in_progress, result)
|
(in_progress, result)
|
||||||
}
|
}
|
||||||
|
@ -228,7 +220,7 @@ impl<'a, 'c> InProgressBuilder<'a, 'c> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'c> BuildTerms for InProgressBuilder<'a, 'c> {
|
impl<'a, 'c> BuildTerms for InProgressBuilder<'a, 'c> {
|
||||||
fn named_tempid(&mut self, name: String) -> TempIdHandle {
|
fn named_tempid(&mut self, name: String) -> ValueRc<TempId> {
|
||||||
self.builder.named_tempid(name)
|
self.builder.named_tempid(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,70 +229,29 @@ impl<'a, 'c> BuildTerms for InProgressBuilder<'a, 'c> {
|
||||||
self.describe(e)
|
self.describe(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn describe<E>(self, entity: E) -> EntityBuilder<InProgressBuilder<'a, 'c>> where E: IntoThing<KnownEntidOr<TempIdHandle>> {
|
fn describe<E>(self, entity: E) -> EntityBuilder<InProgressBuilder<'a, 'c>> where E: Into<EntityPlace<TypedValue>> {
|
||||||
EntityBuilder {
|
EntityBuilder {
|
||||||
builder: self,
|
builder: self,
|
||||||
entity: entity.into_thing(),
|
entity: entity.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add<E, V>(&mut self, e: E, a: KnownEntid, v: V) -> Result<()>
|
fn add<E, A, V>(&mut self, e: E, a: A, v: V) -> Result<()>
|
||||||
where E: IntoThing<KnownEntidOr<TempIdHandle>>,
|
where E: Into<EntityPlace<TypedValue>>,
|
||||||
V: IntoThing<TypedValueOr<TempIdHandle>> {
|
A: Into<AttributePlace>,
|
||||||
|
V: Into<ValuePlace<TypedValue>> {
|
||||||
self.builder.add(e, a, v)
|
self.builder.add(e, a, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn retract<E, V>(&mut self, e: E, a: KnownEntid, v: V) -> Result<()>
|
fn retract<E, A, V>(&mut self, e: E, a: A, v: V) -> Result<()>
|
||||||
where E: IntoThing<KnownEntidOr<TempIdHandle>>,
|
where E: Into<EntityPlace<TypedValue>>,
|
||||||
V: IntoThing<TypedValueOr<TempIdHandle>> {
|
A: Into<AttributePlace>,
|
||||||
|
V: Into<ValuePlace<TypedValue>> {
|
||||||
self.builder.retract(e, a, v)
|
self.builder.retract(e, a, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'c> InProgressBuilder<'a, 'c> {
|
|
||||||
pub fn add_kw<E, V>(&mut self, e: E, a: &Keyword, v: V) -> Result<()>
|
|
||||||
where E: IntoThing<KnownEntidOr<TempIdHandle>>,
|
|
||||||
V: IntoThing<TypedValueOr<TempIdHandle>> {
|
|
||||||
let (attribute, value) = self.extract_kw_value(a, v.into_thing())?;
|
|
||||||
self.add(e, attribute, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn retract_kw<E, V>(&mut self, e: E, a: &Keyword, v: V) -> Result<()>
|
|
||||||
where E: IntoThing<KnownEntidOr<TempIdHandle>>,
|
|
||||||
V: IntoThing<TypedValueOr<TempIdHandle>> {
|
|
||||||
let (attribute, value) = self.extract_kw_value(a, v.into_thing())?;
|
|
||||||
self.retract(e, attribute, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn extract_kw_value(&mut self, a: &Keyword, v: TypedValueOr<TempIdHandle>) -> Result<(KnownEntid, TypedValueOr<TempIdHandle>)> {
|
|
||||||
let attribute: KnownEntid;
|
|
||||||
if let Some((attr, aa)) = self.in_progress.attribute_for_ident(a) {
|
|
||||||
if let Either::Left(ref tv) = v {
|
|
||||||
let provided = tv.value_type();
|
|
||||||
let expected = attr.value_type;
|
|
||||||
if provided != expected {
|
|
||||||
bail!(MentatError::ValueTypeMismatch(provided, expected));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
attribute = aa;
|
|
||||||
} else {
|
|
||||||
bail!(MentatError::UnknownAttribute(a.to_string()));
|
|
||||||
}
|
|
||||||
Ok((attribute, v))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'c> EntityBuilder<InProgressBuilder<'a, 'c>> {
|
impl<'a, 'c> EntityBuilder<InProgressBuilder<'a, 'c>> {
|
||||||
pub fn add_kw<V>(&mut self, a: &Keyword, v: V) -> Result<()>
|
|
||||||
where V: IntoThing<TypedValueOr<TempIdHandle>> {
|
|
||||||
self.builder.add_kw(self.entity.clone(), a, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn retract_kw<V>(&mut self, a: &Keyword, v: V) -> Result<()>
|
|
||||||
where V: IntoThing<TypedValueOr<TempIdHandle>> {
|
|
||||||
self.builder.retract_kw(self.entity.clone(), a, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Build the terms from this builder and transact them against the current
|
/// Build the terms from this builder and transact them against the current
|
||||||
/// `InProgress`. This method _always_ returns the `InProgress` -- failure doesn't
|
/// `InProgress`. This method _always_ returns the `InProgress` -- failure doesn't
|
||||||
/// imply an automatic rollback.
|
/// imply an automatic rollback.
|
||||||
|
@ -315,69 +266,6 @@ impl<'a, 'c> EntityBuilder<InProgressBuilder<'a, 'c>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can't implement Into for Rc<T>.
|
|
||||||
pub trait IntoThing<T>: Sized {
|
|
||||||
fn into_thing(self) -> T;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait FromThing<T> {
|
|
||||||
fn from_thing(v: T) -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> FromThing<T> for T {
|
|
||||||
fn from_thing(v: T) -> T {
|
|
||||||
v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I, F> IntoThing<I> for F where I: FromThing<F> {
|
|
||||||
fn into_thing(self) -> I {
|
|
||||||
I::from_thing(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> FromThing<&'a TempIdHandle> for TypedValueOr<TempIdHandle> {
|
|
||||||
fn from_thing(v: &'a TempIdHandle) -> Self {
|
|
||||||
Either::Right(v.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromThing<TempIdHandle> for TypedValueOr<TempIdHandle> {
|
|
||||||
fn from_thing(v: TempIdHandle) -> Self {
|
|
||||||
Either::Right(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromThing<TypedValue> for TypedValueOr<TempIdHandle> {
|
|
||||||
fn from_thing(v: TypedValue) -> Self {
|
|
||||||
Either::Left(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromThing<TempIdHandle> for KnownEntidOr<TempIdHandle> {
|
|
||||||
fn from_thing(v: TempIdHandle) -> Self {
|
|
||||||
Either::Right(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> FromThing<&'a KnownEntid> for KnownEntidOr<TempIdHandle> {
|
|
||||||
fn from_thing(v: &'a KnownEntid) -> Self {
|
|
||||||
Either::Left(v.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromThing<KnownEntid> for KnownEntidOr<TempIdHandle> {
|
|
||||||
fn from_thing(v: KnownEntid) -> Self {
|
|
||||||
Either::Left(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromThing<KnownEntid> for TypedValueOr<TempIdHandle> {
|
|
||||||
fn from_thing(v: KnownEntid) -> Self {
|
|
||||||
Either::Left(v.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod testing {
|
mod testing {
|
||||||
extern crate mentat_db;
|
extern crate mentat_db;
|
||||||
|
@ -386,6 +274,8 @@ mod testing {
|
||||||
Conn,
|
Conn,
|
||||||
Entid,
|
Entid,
|
||||||
HasSchema,
|
HasSchema,
|
||||||
|
KnownEntid,
|
||||||
|
MentatError,
|
||||||
Queryable,
|
Queryable,
|
||||||
TypedValue,
|
TypedValue,
|
||||||
TxReport,
|
TxReport,
|
||||||
|
@ -421,7 +311,7 @@ mod testing {
|
||||||
let mut in_progress = conn.begin_transaction(&mut sqlite).expect("begun successfully");
|
let mut in_progress = conn.begin_transaction(&mut sqlite).expect("begun successfully");
|
||||||
|
|
||||||
// This should fail: unrecognized entid.
|
// This should fail: unrecognized entid.
|
||||||
match in_progress.transact_terms(terms, tempids).expect_err("expected transact to fail") {
|
match in_progress.transact_entities(terms).expect_err("expected transact to fail") {
|
||||||
MentatError::DbError(e) => {
|
MentatError::DbError(e) => {
|
||||||
assert_eq!(e.kind(), mentat_db::DbErrorKind::UnrecognizedEntid(999));
|
assert_eq!(e.kind(), mentat_db::DbErrorKind::UnrecognizedEntid(999));
|
||||||
},
|
},
|
||||||
|
@ -456,7 +346,7 @@ mod testing {
|
||||||
let e_x = builder.named_tempid("x".into());
|
let e_x = builder.named_tempid("x".into());
|
||||||
let v_many_1 = TypedValue::typed_string("Some text");
|
let v_many_1 = TypedValue::typed_string("Some text");
|
||||||
let v_many_2 = TypedValue::typed_string("Other text");
|
let v_many_2 = TypedValue::typed_string("Other text");
|
||||||
builder.add_kw(e_x.clone(), &kw!(:foo/many), v_many_1).expect("add succeeded");
|
builder.add(e_x.clone(), kw!(:foo/many), v_many_1).expect("add succeeded");
|
||||||
builder.add(e_x.clone(), a_many, v_many_2).expect("add succeeded");
|
builder.add(e_x.clone(), a_many, v_many_2).expect("add succeeded");
|
||||||
builder.commit().expect("commit succeeded");
|
builder.commit().expect("commit succeeded");
|
||||||
}
|
}
|
||||||
|
@ -510,7 +400,7 @@ mod testing {
|
||||||
assert_eq!(tempids.len(), 2);
|
assert_eq!(tempids.len(), 2);
|
||||||
assert_eq!(terms.len(), 4);
|
assert_eq!(terms.len(), 4);
|
||||||
|
|
||||||
report = in_progress.transact_terms(terms, tempids).expect("add succeeded");
|
report = in_progress.transact_entities(terms).expect("add succeeded");
|
||||||
let x = report.tempids.get("x").expect("our tempid has an ID");
|
let x = report.tempids.get("x").expect("our tempid has an ID");
|
||||||
let y = report.tempids.get("y").expect("our tempid has an ID");
|
let y = report.tempids.get("y").expect("our tempid has an ID");
|
||||||
assert_eq!(in_progress.lookup_value_for_attribute(*y, &foo_ref).expect("lookup succeeded"),
|
assert_eq!(in_progress.lookup_value_for_attribute(*y, &foo_ref).expect("lookup succeeded"),
|
||||||
|
|
14
src/store.rs
14
src/store.rs
|
@ -607,12 +607,12 @@ mod tests {
|
||||||
let name = format!("todo{}", i);
|
let name = format!("todo{}", i);
|
||||||
let uuid = Uuid::new_v4();
|
let uuid = Uuid::new_v4();
|
||||||
let mut builder = in_progress.builder().describe_tempid(&name);
|
let mut builder = in_progress.builder().describe_tempid(&name);
|
||||||
builder.add_kw(&kw!(:todo/uuid), TypedValue::Uuid(uuid)).expect("Expected added uuid");
|
builder.add(kw!(:todo/uuid), TypedValue::Uuid(uuid)).expect("Expected added uuid");
|
||||||
changeset.insert(uuid_entid.clone());
|
changeset.insert(uuid_entid.clone());
|
||||||
builder.add_kw(&kw!(:todo/name), TypedValue::typed_string(&name)).expect("Expected added name");
|
builder.add(kw!(:todo/name), TypedValue::typed_string(&name)).expect("Expected added name");
|
||||||
changeset.insert(name_entid.clone());
|
changeset.insert(name_entid.clone());
|
||||||
if i % 2 == 0 {
|
if i % 2 == 0 {
|
||||||
builder.add_kw(&kw!(:todo/completion_date), TypedValue::current_instant()).expect("Expected added date");
|
builder.add(kw!(:todo/completion_date), TypedValue::current_instant()).expect("Expected added date");
|
||||||
changeset.insert(date_entid.clone());
|
changeset.insert(date_entid.clone());
|
||||||
}
|
}
|
||||||
let (ip, r) = builder.transact();
|
let (ip, r) = builder.transact();
|
||||||
|
@ -622,8 +622,8 @@ mod tests {
|
||||||
in_progress = ip;
|
in_progress = ip;
|
||||||
}
|
}
|
||||||
let mut builder = in_progress.builder().describe_tempid("Label");
|
let mut builder = in_progress.builder().describe_tempid("Label");
|
||||||
builder.add_kw(&kw!(:label/name), TypedValue::typed_string("Label 1")).expect("Expected added name");
|
builder.add(kw!(:label/name), TypedValue::typed_string("Label 1")).expect("Expected added name");
|
||||||
builder.add_kw(&kw!(:label/color), TypedValue::typed_string("blue")).expect("Expected added color");
|
builder.add(kw!(:label/color), TypedValue::typed_string("blue")).expect("Expected added color");
|
||||||
builder.commit().expect("expect transaction to occur");
|
builder.commit().expect("expect transaction to occur");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,8 +678,8 @@ mod tests {
|
||||||
for i in 0..3 {
|
for i in 0..3 {
|
||||||
let name = format!("label{}", i);
|
let name = format!("label{}", i);
|
||||||
let mut builder = in_progress.builder().describe_tempid(&name);
|
let mut builder = in_progress.builder().describe_tempid(&name);
|
||||||
builder.add_kw(&kw!(:label/name), TypedValue::typed_string(&name)).expect("Expected added name");
|
builder.add(kw!(:label/name), TypedValue::typed_string(&name)).expect("Expected added name");
|
||||||
builder.add_kw(&kw!(:label/color), TypedValue::typed_string("blue")).expect("Expected added color");
|
builder.add(kw!(:label/color), TypedValue::typed_string("blue")).expect("Expected added color");
|
||||||
let (ip, _) = builder.transact();
|
let (ip, _) = builder.transact();
|
||||||
in_progress = ip;
|
in_progress = ip;
|
||||||
}
|
}
|
||||||
|
|
|
@ -812,14 +812,14 @@ impl VocabularySource for SimpleVocabularySource {
|
||||||
impl<'a, 'c> VocabularyMechanics for InProgress<'a, 'c> {
|
impl<'a, 'c> VocabularyMechanics for InProgress<'a, 'c> {
|
||||||
/// Turn the vocabulary into datoms, transact them, and on success return the outcome.
|
/// Turn the vocabulary into datoms, transact them, and on success return the outcome.
|
||||||
fn install_vocabulary(&mut self, definition: &Definition) -> Result<VocabularyOutcome> {
|
fn install_vocabulary(&mut self, definition: &Definition) -> Result<VocabularyOutcome> {
|
||||||
let (terms, tempids) = definition.description(self)?;
|
let (terms, _tempids) = definition.description(self)?;
|
||||||
self.transact_terms(terms, tempids)?;
|
self.transact_entities(terms)?;
|
||||||
Ok(VocabularyOutcome::Installed)
|
Ok(VocabularyOutcome::Installed)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn install_attributes_for<'definition>(&mut self, definition: &'definition Definition, attributes: Vec<&'definition (Keyword, Attribute)>) -> Result<VocabularyOutcome> {
|
fn install_attributes_for<'definition>(&mut self, definition: &'definition Definition, attributes: Vec<&'definition (Keyword, Attribute)>) -> Result<VocabularyOutcome> {
|
||||||
let (terms, tempids) = definition.description_for_attributes(&attributes, self, None)?;
|
let (terms, _tempids) = definition.description_for_attributes(&attributes, self, None)?;
|
||||||
self.transact_terms(terms, tempids)?;
|
self.transact_entities(terms)?;
|
||||||
Ok(VocabularyOutcome::InstalledMissingAttributes)
|
Ok(VocabularyOutcome::InstalledMissingAttributes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -834,8 +834,8 @@ impl<'a, 'c> VocabularyMechanics for InProgress<'a, 'c> {
|
||||||
|
|
||||||
// TODO: don't do work for attributes that are unchanged. Here we rely on the transactor
|
// TODO: don't do work for attributes that are unchanged. Here we rely on the transactor
|
||||||
// to elide duplicate datoms.
|
// to elide duplicate datoms.
|
||||||
let (terms, tempids) = definition.description_diff(self, &from_version)?;
|
let (terms, _tempids) = definition.description_diff(self, &from_version)?;
|
||||||
self.transact_terms(terms, tempids)?;
|
self.transact_entities(terms)?;
|
||||||
|
|
||||||
definition.post(self, &from_version)?;
|
definition.post(self, &from_version)?;
|
||||||
Ok(VocabularyOutcome::Upgraded)
|
Ok(VocabularyOutcome::Upgraded)
|
||||||
|
|
Loading…
Reference in a new issue