This commit is contained in:
commit
99deb87b9f
18 changed files with 397 additions and 315 deletions
|
@ -60,9 +60,14 @@ pub use cache::{
|
|||
|
||||
/// Core types defining a Mentat knowledge base.
|
||||
mod types;
|
||||
mod tx_report;
|
||||
mod value_type_set;
|
||||
mod sql_types;
|
||||
|
||||
pub use tx_report::{
|
||||
TxReport,
|
||||
};
|
||||
|
||||
pub use types::{
|
||||
Binding,
|
||||
Entid,
|
||||
|
@ -365,7 +370,6 @@ impl HasSchema for Schema {
|
|||
}
|
||||
}
|
||||
|
||||
pub mod intern_set;
|
||||
pub mod counter;
|
||||
pub mod util;
|
||||
|
||||
|
|
38
core/src/tx_report.rs
Normal file
38
core/src/tx_report.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2018 Mozilla
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
// this file except in compliance with the License. You may obtain a copy of the
|
||||
// License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::collections::{
|
||||
BTreeMap,
|
||||
};
|
||||
|
||||
use ::{
|
||||
DateTime,
|
||||
Entid,
|
||||
Utc,
|
||||
};
|
||||
|
||||
/// A transaction report summarizes an applied transaction.
|
||||
#[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
||||
pub struct TxReport {
|
||||
/// The transaction ID of the transaction.
|
||||
pub tx_id: Entid,
|
||||
|
||||
/// The timestamp when the transaction began to be committed.
|
||||
pub tx_instant: DateTime<Utc>,
|
||||
|
||||
/// A map from string literal tempid to resolved or allocated entid.
|
||||
///
|
||||
/// Every string literal tempid presented to the transactor either resolves via upsert to an
|
||||
/// existing entid, or is allocated a new entid. (It is possible for multiple distinct string
|
||||
/// literal tempids to all unify to a single freshly allocated entid.)
|
||||
pub tempids: BTreeMap<String, Entid>,
|
||||
}
|
|
@ -47,6 +47,14 @@ use ::edn::{
|
|||
ValueRc,
|
||||
};
|
||||
|
||||
use ::edn::entities::{
|
||||
AttributePlace,
|
||||
EntidOrIdent,
|
||||
EntityPlace,
|
||||
ValuePlace,
|
||||
TransactableValueMarker,
|
||||
};
|
||||
|
||||
use values;
|
||||
|
||||
/// 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
|
||||
/// particular set. Mentat recognizes the following :db/valueType values.
|
||||
#[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.
|
||||
}
|
||||
|
||||
/// `TypedValue` is the value type for programmatic use in transaction builders.
|
||||
impl TransactableValueMarker for TypedValue {}
|
||||
|
||||
/// The values bound in a query specification can be:
|
||||
///
|
||||
/// * Vecs of structured values, for multi-valued component attributes or nested expressions.
|
||||
|
|
19
db/src/db.rs
19
db/src/db.rs
|
@ -1119,20 +1119,22 @@ mod tests {
|
|||
use debug;
|
||||
use errors;
|
||||
use edn;
|
||||
use mentat_core::{
|
||||
HasSchema,
|
||||
Keyword,
|
||||
KnownEntid,
|
||||
attribute,
|
||||
};
|
||||
use mentat_core::intern_set::{
|
||||
use edn::{
|
||||
InternSet,
|
||||
};
|
||||
use mentat_core::util::Either::*;
|
||||
use edn::entities::{
|
||||
OpType,
|
||||
TempId,
|
||||
};
|
||||
|
||||
use mentat_core::{
|
||||
HasSchema,
|
||||
Keyword,
|
||||
KnownEntid,
|
||||
TxReport,
|
||||
attribute,
|
||||
};
|
||||
use mentat_core::util::Either::*;
|
||||
use rusqlite;
|
||||
use std::collections::{
|
||||
BTreeMap,
|
||||
|
@ -1141,7 +1143,6 @@ mod tests {
|
|||
Term,
|
||||
TermWithTempIds,
|
||||
};
|
||||
use types::TxReport;
|
||||
use tx::{
|
||||
transact_terms,
|
||||
};
|
||||
|
|
|
@ -17,7 +17,6 @@ use std::collections::{
|
|||
BTreeSet,
|
||||
HashMap,
|
||||
};
|
||||
use std::rc::Rc;
|
||||
|
||||
use mentat_core::KnownEntid;
|
||||
|
||||
|
@ -27,6 +26,14 @@ use edn;
|
|||
use edn::{
|
||||
SpannedValue,
|
||||
ValueAndSpan,
|
||||
ValueRc,
|
||||
};
|
||||
use edn::entities;
|
||||
use edn::entities::{
|
||||
EntityPlace,
|
||||
OpType,
|
||||
TempId,
|
||||
TxFunction,
|
||||
};
|
||||
|
||||
use errors;
|
||||
|
@ -47,13 +54,6 @@ use types::{
|
|||
TypedValue,
|
||||
ValueType,
|
||||
};
|
||||
use edn::entities;
|
||||
use edn::entities::{
|
||||
EntityPlace,
|
||||
OpType,
|
||||
TempId,
|
||||
TxFunction,
|
||||
};
|
||||
|
||||
impl TransactableValue for ValueAndSpan {
|
||||
fn into_typed_value(self, schema: &Schema, value_type: ValueType) -> Result<TypedValue> {
|
||||
|
@ -72,7 +72,7 @@ impl TransactableValue for ValueAndSpan {
|
|||
bail!(DbErrorKind::InputError(errors::InputError::BadEntityPlace))
|
||||
}
|
||||
},
|
||||
Text(v) => Ok(EntityPlace::TempId(TempId::External(v))),
|
||||
Text(v) => Ok(EntityPlace::TempId(TempId::External(v).into())),
|
||||
List(ls) => {
|
||||
let mut it = ls.iter();
|
||||
match (it.next().map(|x| &x.inner), it.next(), it.next(), it.next()) {
|
||||
|
@ -107,7 +107,7 @@ impl TransactableValue for ValueAndSpan {
|
|||
}
|
||||
|
||||
fn as_tempid(&self) -> Option<TempId> {
|
||||
self.inner.as_text().cloned().map(TempId::External)
|
||||
self.inner.as_text().cloned().map(TempId::External).map(|v| v.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,7 @@ impl TransactableValue for TypedValue {
|
|||
match self {
|
||||
TypedValue::Ref(x) => Ok(EntityPlace::Entid(entities::EntidOrIdent::Entid(x))),
|
||||
TypedValue::Keyword(x) => Ok(EntityPlace::Entid(entities::EntidOrIdent::Ident((*x).clone()))),
|
||||
TypedValue::String(x) => Ok(EntityPlace::TempId(TempId::External((*x).clone()))),
|
||||
TypedValue::String(x) => Ok(EntityPlace::TempId(TempId::External((*x).clone()).into())),
|
||||
TypedValue::Boolean(_) |
|
||||
TypedValue::Long(_) |
|
||||
TypedValue::Double(_) |
|
||||
|
@ -134,7 +134,7 @@ impl TransactableValue for TypedValue {
|
|||
|
||||
fn as_tempid(&self) -> Option<TempId> {
|
||||
match self {
|
||||
&TypedValue::String(ref s) => Some(TempId::External((**s).clone())),
|
||||
&TypedValue::String(ref s) => Some(TempId::External((**s).clone()).into()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -150,10 +150,10 @@ use self::Either::*;
|
|||
pub type KnownEntidOr<T> = Either<KnownEntid, T>;
|
||||
pub type TypedValueOr<T> = Either<TypedValue, T>;
|
||||
|
||||
pub type TempIdHandle = Rc<TempId>;
|
||||
pub type TempIdHandle = ValueRc<TempId>;
|
||||
pub type TempIdMap = HashMap<TempIdHandle, KnownEntid>;
|
||||
|
||||
pub type LookupRef = Rc<AVPair>;
|
||||
pub type LookupRef = ValueRc<AVPair>;
|
||||
|
||||
/// Internal representation of an entid on its way to resolution. We either have the simple case (a
|
||||
/// numeric entid), a lookup-ref that still needs to be resolved (an atomized [a v] pair), or a temp
|
||||
|
|
|
@ -106,7 +106,6 @@ pub use types::{
|
|||
DB,
|
||||
PartitionMap,
|
||||
TransactableValue,
|
||||
TxReport,
|
||||
};
|
||||
|
||||
pub fn to_namespaced_keyword(s: &str) -> Result<symbols::Keyword> {
|
||||
|
|
30
db/src/tx.rs
30
db/src/tx.rs
|
@ -56,9 +56,6 @@ use std::collections::{
|
|||
use std::iter::{
|
||||
once,
|
||||
};
|
||||
use std::rc::{
|
||||
Rc,
|
||||
};
|
||||
|
||||
use db;
|
||||
use db::{
|
||||
|
@ -66,6 +63,7 @@ use db::{
|
|||
PartitionMapping,
|
||||
};
|
||||
use edn::{
|
||||
InternSet,
|
||||
Keyword,
|
||||
};
|
||||
use entids;
|
||||
|
@ -96,13 +94,12 @@ use mentat_core::{
|
|||
DateTime,
|
||||
KnownEntid,
|
||||
Schema,
|
||||
TxReport,
|
||||
Utc,
|
||||
attribute,
|
||||
now,
|
||||
};
|
||||
|
||||
use mentat_core::intern_set::InternSet;
|
||||
|
||||
use edn::entities as entmod;
|
||||
use edn::entities::{
|
||||
AttributePlace,
|
||||
|
@ -123,7 +120,6 @@ use types::{
|
|||
Entid,
|
||||
PartitionMap,
|
||||
TransactableValue,
|
||||
TxReport,
|
||||
TypedValue,
|
||||
ValueType,
|
||||
};
|
||||
|
@ -304,15 +300,11 @@ impl<'conn, 'a, W> Tx<'conn, 'a, W> where W: TransactWatcher {
|
|||
Ok(self.lookup_refs.intern((lr_a, lr_typed_value)))
|
||||
}
|
||||
|
||||
fn intern_temp_id(&mut self, temp_id: TempId) -> Rc<TempId> {
|
||||
self.temp_ids.intern(temp_id)
|
||||
}
|
||||
|
||||
/// Allocate private internal tempids reserved for Mentat. Internal tempids just need to be
|
||||
/// unique within one transaction; they should never escape a transaction.
|
||||
fn allocate_mentat_id<W: TransactableValue>(&mut self) -> entmod::EntityPlace<W> {
|
||||
self.mentat_id_count += 1;
|
||||
entmod::EntityPlace::TempId(TempId::Internal(self.mentat_id_count))
|
||||
entmod::EntityPlace::TempId(TempId::Internal(self.mentat_id_count).into())
|
||||
}
|
||||
|
||||
fn entity_e_into_term_e<W: TransactableValue>(&mut self, x: entmod::EntityPlace<W>) -> Result<KnownEntidOr<LookupRefOrTempId>> {
|
||||
|
@ -326,7 +318,7 @@ impl<'conn, 'a, W> Tx<'conn, 'a, W> where W: TransactWatcher {
|
|||
},
|
||||
|
||||
entmod::EntityPlace::TempId(e) => {
|
||||
Ok(Either::Right(LookupRefOrTempId::TempId(self.intern_temp_id(e))))
|
||||
Ok(Either::Right(LookupRefOrTempId::TempId(self.temp_ids.intern(e))))
|
||||
},
|
||||
|
||||
entmod::EntityPlace::LookupRef(ref lookup_ref) => {
|
||||
|
@ -372,7 +364,7 @@ impl<'conn, 'a, W> Tx<'conn, 'a, W> where W: TransactWatcher {
|
|||
// that the given value is in the attribute's value set, or (in
|
||||
// limited cases) coerce the value into the attribute's value set.
|
||||
match v.as_tempid() {
|
||||
Some(tempid) => Ok(Either::Right(LookupRefOrTempId::TempId(self.intern_temp_id(tempid)))),
|
||||
Some(tempid) => Ok(Either::Right(LookupRefOrTempId::TempId(self.temp_ids.intern(tempid)))),
|
||||
None => {
|
||||
if let TypedValue::Ref(entid) = v.into_typed_value(&self.schema, ValueType::Ref)? {
|
||||
Ok(Either::Left(KnownEntid(entid)))
|
||||
|
@ -388,7 +380,7 @@ impl<'conn, 'a, W> Tx<'conn, 'a, W> where W: TransactWatcher {
|
|||
Ok(Either::Left(KnownEntid(self.entity_a_into_term_a(entid)?))),
|
||||
|
||||
entmod::ValuePlace::TempId(tempid) =>
|
||||
Ok(Either::Right(LookupRefOrTempId::TempId(self.intern_temp_id(tempid)))),
|
||||
Ok(Either::Right(LookupRefOrTempId::TempId(self.temp_ids.intern(tempid)))),
|
||||
|
||||
entmod::ValuePlace::LookupRef(ref lookup_ref) =>
|
||||
Ok(Either::Right(LookupRefOrTempId::LookupRef(self.intern_lookup_ref(lookup_ref)?))),
|
||||
|
@ -459,7 +451,7 @@ impl<'conn, 'a, W> Tx<'conn, 'a, W> where W: TransactWatcher {
|
|||
// limited cases) coerce the value into the attribute's value set.
|
||||
if attribute.value_type == ValueType::Ref {
|
||||
match v.as_tempid() {
|
||||
Some(tempid) => Either::Right(LookupRefOrTempId::TempId(in_process.intern_temp_id(tempid))),
|
||||
Some(tempid) => Either::Right(LookupRefOrTempId::TempId(in_process.temp_ids.intern(tempid))),
|
||||
None => v.into_typed_value(&self.schema, attribute.value_type).map(Either::Left)?,
|
||||
}
|
||||
} else {
|
||||
|
@ -471,7 +463,7 @@ impl<'conn, 'a, W> Tx<'conn, 'a, W> where W: TransactWatcher {
|
|||
Either::Left(TypedValue::Ref(in_process.entity_a_into_term_a(entid)?)),
|
||||
|
||||
entmod::ValuePlace::TempId(tempid) =>
|
||||
Either::Right(LookupRefOrTempId::TempId(in_process.intern_temp_id(tempid))),
|
||||
Either::Right(LookupRefOrTempId::TempId(in_process.temp_ids.intern(tempid))),
|
||||
|
||||
entmod::ValuePlace::LookupRef(ref lookup_ref) => {
|
||||
if attribute.value_type != ValueType::Ref {
|
||||
|
@ -622,7 +614,7 @@ impl<'conn, 'a, W> Tx<'conn, 'a, W> where W: TransactWatcher {
|
|||
let (terms_with_temp_ids_and_lookup_refs, tempid_set, lookup_ref_set) = self.entities_into_terms_with_temp_ids_and_lookup_refs(entities)?;
|
||||
|
||||
// Pipeline stage 2: resolve lookup refs -> terms with tempids.
|
||||
let lookup_ref_avs: Vec<&(i64, TypedValue)> = lookup_ref_set.inner.iter().map(|rc| &**rc).collect();
|
||||
let lookup_ref_avs: Vec<&(i64, TypedValue)> = lookup_ref_set.iter().map(|rc| &**rc).collect();
|
||||
let lookup_ref_map: AVMap = self.store.resolve_avs(&lookup_ref_avs[..])?;
|
||||
|
||||
let terms_with_temp_ids = self.resolve_lookup_refs(&lookup_ref_map, terms_with_temp_ids_and_lookup_refs)?;
|
||||
|
@ -703,8 +695,8 @@ impl<'conn, 'a, W> Tx<'conn, 'a, W> where W: TransactWatcher {
|
|||
}
|
||||
|
||||
// Verify that every tempid we interned either resolved or has been allocated.
|
||||
assert_eq!(tempids.len(), tempid_set.inner.len());
|
||||
for tempid in &tempid_set.inner {
|
||||
assert_eq!(tempids.len(), tempid_set.len());
|
||||
for tempid in tempid_set.iter() {
|
||||
assert!(tempids.contains_key(&**tempid));
|
||||
}
|
||||
|
||||
|
|
|
@ -95,23 +95,6 @@ pub type AVMap<'a> = HashMap<&'a AVPair, Entid>;
|
|||
// represents a set of entids that are correspond to attributes
|
||||
pub type AttributeSet = BTreeSet<Entid>;
|
||||
|
||||
/// A transaction report summarizes an applied transaction.
|
||||
#[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
||||
pub struct TxReport {
|
||||
/// The transaction ID of the transaction.
|
||||
pub tx_id: Entid,
|
||||
|
||||
/// The timestamp when the transaction began to be committed.
|
||||
pub tx_instant: DateTime<Utc>,
|
||||
|
||||
/// A map from string literal tempid to resolved or allocated entid.
|
||||
///
|
||||
/// Every string literal tempid presented to the transactor either resolves via upsert to an
|
||||
/// existing entid, or is allocated a new entid. (It is possible for multiple distinct string
|
||||
/// literal tempids to all unify to a single freshly allocated entid.)
|
||||
pub tempids: BTreeMap<String, Entid>,
|
||||
}
|
||||
|
||||
/// The transactor is tied to `edn::ValueAndSpan` right now, but in the future we'd like to support
|
||||
/// `TypedValue` directly for programmatic use. `TransactableValue` encapsulates the interface
|
||||
/// value types (i.e., values in the value place) need to support to be transacted.
|
||||
|
|
|
@ -260,7 +260,7 @@ tx_function -> TxFunction
|
|||
= "(" __ n:$(symbol_name) __ ")" { TxFunction { op: PlainSymbol::plain(n) } }
|
||||
|
||||
entity_place -> EntityPlace<ValueAndSpan>
|
||||
= v:raw_text { EntityPlace::TempId(TempId::External(v)) }
|
||||
= v:raw_text { EntityPlace::TempId(TempId::External(v).into()) }
|
||||
/ v:entid { EntityPlace::Entid(v) }
|
||||
/ v:lookup_ref { EntityPlace::LookupRef(v) }
|
||||
/ v:tx_function { EntityPlace::TxFunction(v) }
|
||||
|
|
|
@ -13,11 +13,29 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
|
||||
use value_rc::{
|
||||
ValueRc,
|
||||
};
|
||||
|
||||
use symbols::{
|
||||
Keyword,
|
||||
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`),
|
||||
/// or an internal tempid allocated by Mentat itself.
|
||||
#[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
||||
|
@ -50,6 +68,18 @@ pub enum EntidOrIdent {
|
|||
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 {
|
||||
pub fn unreversed(&self) -> Option<EntidOrIdent> {
|
||||
match self {
|
||||
|
@ -93,7 +123,7 @@ pub enum ValuePlace<V> {
|
|||
Entid(EntidOrIdent),
|
||||
// We never know at parse-time whether a string is really a tempid, but we will often know when
|
||||
// building entities programmatically.
|
||||
TempId(TempId),
|
||||
TempId(ValueRc<TempId>),
|
||||
LookupRef(LookupRef<V>),
|
||||
TxFunction(TxFunction),
|
||||
Vector(Vec<ValuePlace<V>>),
|
||||
|
@ -101,19 +131,103 @@ pub enum ValuePlace<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)]
|
||||
pub enum EntityPlace<V> {
|
||||
Entid(EntidOrIdent),
|
||||
TempId(TempId),
|
||||
TempId(ValueRc<TempId>),
|
||||
LookupRef(LookupRef<V>),
|
||||
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)]
|
||||
pub enum AttributePlace {
|
||||
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)]
|
||||
pub enum OpType {
|
||||
Add,
|
||||
|
|
|
@ -12,7 +12,14 @@
|
|||
|
||||
use std::collections::HashSet;
|
||||
use std::hash::Hash;
|
||||
use std::rc::Rc;
|
||||
use std::ops::{
|
||||
Deref,
|
||||
DerefMut,
|
||||
};
|
||||
|
||||
use ::{
|
||||
ValueRc,
|
||||
};
|
||||
|
||||
/// An `InternSet` allows to "intern" some potentially large values, maintaining a single value
|
||||
/// instance owned by the `InternSet` and leaving consumers with lightweight ref-counted handles to
|
||||
|
@ -23,7 +30,21 @@ use std::rc::Rc;
|
|||
/// See https://en.wikipedia.org/wiki/String_interning for discussion.
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct InternSet<T> where T: Eq + Hash {
|
||||
pub inner: HashSet<Rc<T>>,
|
||||
inner: HashSet<ValueRc<T>>,
|
||||
}
|
||||
|
||||
impl<T> Deref for InternSet<T> where T: Eq + Hash {
|
||||
type Target = HashSet<ValueRc<T>>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for InternSet<T> where T: Eq + Hash {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> InternSet<T> where T: Eq + Hash {
|
||||
|
@ -33,20 +54,15 @@ 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.
|
||||
///
|
||||
/// ```
|
||||
/// use std::rc::Rc;
|
||||
/// use mentat_core::intern_set::InternSet;
|
||||
/// use edn::{InternSet, ValueRc};
|
||||
///
|
||||
/// let mut s = InternSet::new();
|
||||
///
|
||||
/// let one = "foo".to_string();
|
||||
/// let two = Rc::new("foo".to_string());
|
||||
/// let two = ValueRc::new("foo".to_string());
|
||||
///
|
||||
/// let out_one = s.intern(one);
|
||||
/// assert_eq!(out_one, two);
|
||||
|
@ -54,11 +70,11 @@ impl<T> InternSet<T> where T: Eq + Hash {
|
|||
///
|
||||
/// let out_two = s.intern(two);
|
||||
/// assert_eq!(out_one, out_two);
|
||||
/// assert_eq!(1, s.inner.len());
|
||||
/// assert_eq!(1, s.len());
|
||||
/// // assert!(&out_one.ptr_eq(&out_two)); // Nightly-only.
|
||||
/// ```
|
||||
pub fn intern<R: Into<Rc<T>>>(&mut self, value: R) -> Rc<T> {
|
||||
let key: Rc<T> = value.into();
|
||||
pub fn intern<R: Into<ValueRc<T>>>(&mut self, value: R) -> ValueRc<T> {
|
||||
let key: ValueRc<T> = value.into();
|
||||
if self.inner.insert(key.clone()) {
|
||||
key
|
||||
} else {
|
|
@ -23,6 +23,10 @@ extern crate serde;
|
|||
extern crate serde_derive;
|
||||
|
||||
pub mod entities;
|
||||
pub mod intern_set;
|
||||
pub use intern_set::{
|
||||
InternSet,
|
||||
};
|
||||
// Intentionally not pub.
|
||||
mod namespaceable_name;
|
||||
pub mod query;
|
||||
|
|
|
@ -120,7 +120,6 @@ pub use mentat::entity_builder::{
|
|||
BuildTerms,
|
||||
EntityBuilder,
|
||||
InProgressBuilder,
|
||||
IntoThing,
|
||||
};
|
||||
|
||||
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> {
|
||||
assert_not_null!(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
|
||||
|
@ -392,7 +391,7 @@ pub unsafe extern "C" fn store_entity_builder_from_entid<'a, 'c>(store: *mut Sto
|
|||
assert_not_null!(store);
|
||||
let store = &mut *store;
|
||||
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)
|
||||
}
|
||||
|
@ -418,7 +417,7 @@ pub unsafe extern "C" fn in_progress_builder_add_string<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -441,7 +440,7 @@ pub unsafe extern "C" fn in_progress_builder_add_long<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -465,7 +464,7 @@ pub unsafe extern "C" fn in_progress_builder_add_ref<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -490,7 +489,7 @@ pub unsafe extern "C" fn in_progress_builder_add_keyword<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -514,7 +513,7 @@ pub unsafe extern "C" fn in_progress_builder_add_boolean<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -538,7 +537,7 @@ pub unsafe extern "C" fn in_progress_builder_add_double<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -562,7 +561,7 @@ pub unsafe extern "C" fn in_progress_builder_add_timestamp<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -588,7 +587,7 @@ pub unsafe extern "C" fn in_progress_builder_add_uuid<'a, 'c>(
|
|||
let value = &*value;
|
||||
let value = Uuid::from_bytes(value).expect("valid uuid");
|
||||
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`.
|
||||
|
@ -612,7 +611,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_string<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -636,7 +635,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_long<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -660,7 +659,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_ref<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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 kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -709,7 +708,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_boolean<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -733,7 +732,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_double<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -757,7 +756,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_timestamp<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -785,7 +784,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_uuid<'a, 'c>(
|
|||
let value = &*value;
|
||||
let value = Uuid::from_bytes(value).expect("valid uuid");
|
||||
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
|
||||
|
@ -842,7 +841,7 @@ pub unsafe extern "C" fn entity_builder_add_string<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -865,7 +864,7 @@ pub unsafe extern "C" fn entity_builder_add_long<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -888,7 +887,7 @@ pub unsafe extern "C" fn entity_builder_add_ref<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -911,7 +910,7 @@ pub unsafe extern "C" fn entity_builder_add_keyword<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -934,7 +933,7 @@ pub unsafe extern "C" fn entity_builder_add_boolean<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -957,7 +956,7 @@ pub unsafe extern "C" fn entity_builder_add_double<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -980,7 +979,7 @@ pub unsafe extern "C" fn entity_builder_add_timestamp<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -1005,7 +1004,7 @@ pub unsafe extern "C" fn entity_builder_add_uuid<'a, 'c>(
|
|||
let value = &*value;
|
||||
let value = Uuid::from_bytes(value).expect("valid uuid");
|
||||
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`.
|
||||
|
@ -1028,7 +1027,7 @@ pub unsafe extern "C" fn entity_builder_retract_string<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -1051,7 +1050,7 @@ pub unsafe extern "C" fn entity_builder_retract_long<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -1074,7 +1073,7 @@ pub unsafe extern "C" fn entity_builder_retract_ref<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -1097,7 +1096,7 @@ pub unsafe extern "C" fn entity_builder_retract_keyword<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -1120,7 +1119,7 @@ pub unsafe extern "C" fn entity_builder_retract_boolean<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -1143,7 +1142,7 @@ pub unsafe extern "C" fn entity_builder_retract_double<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -1166,7 +1165,7 @@ pub unsafe extern "C" fn entity_builder_retract_timestamp<'a, 'c>(
|
|||
let builder = &mut *builder;
|
||||
let kw = kw_from_string(c_char_to_string(kw));
|
||||
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`.
|
||||
|
@ -1192,7 +1191,7 @@ pub unsafe extern "C" fn entity_builder_retract_uuid<'a, 'c>(
|
|||
let value = &*value;
|
||||
let value = Uuid::from_bytes(value).expect("valid uuid");
|
||||
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
|
||||
|
|
11
src/conn.rs
11
src/conn.rs
|
@ -41,6 +41,9 @@ use rusqlite::{
|
|||
};
|
||||
|
||||
use edn;
|
||||
use edn::{
|
||||
InternSet,
|
||||
};
|
||||
|
||||
use mentat_core::{
|
||||
Attribute,
|
||||
|
@ -50,13 +53,12 @@ use mentat_core::{
|
|||
Keyword,
|
||||
Schema,
|
||||
StructuredMap,
|
||||
TxReport,
|
||||
TypedValue,
|
||||
ValueRc,
|
||||
ValueType,
|
||||
};
|
||||
|
||||
use mentat_core::intern_set::InternSet;
|
||||
|
||||
use mentat_db::cache::{
|
||||
InProgressCacheTransactWatcher,
|
||||
InProgressSQLiteAttributeCache,
|
||||
|
@ -73,7 +75,6 @@ use mentat_db::{
|
|||
TransactWatcher,
|
||||
TxObservationService,
|
||||
TxObserver,
|
||||
TxReport,
|
||||
};
|
||||
|
||||
use mentat_db::internal_types::TermWithTempIds;
|
||||
|
@ -401,8 +402,8 @@ impl<'a, 'c> InProgress<'a, 'c> {
|
|||
/// This exists so you can make your own.
|
||||
pub fn transact_builder(&mut self, builder: TermBuilder) -> Result<TxReport> {
|
||||
builder.build()
|
||||
.and_then(|(terms, tempid_set)| {
|
||||
self.transact_terms(terms, tempid_set)
|
||||
.and_then(|(terms, _tempid_set)| {
|
||||
self.transact_entities(terms)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -50,34 +50,27 @@
|
|||
//
|
||||
// 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
|
||||
// the transactor -- is intimately tied to EDN and to spanned values.
|
||||
// We probably need both, but this file provides the latter.
|
||||
|
||||
use mentat_core::{
|
||||
HasSchema,
|
||||
KnownEntid,
|
||||
Keyword,
|
||||
TypedValue,
|
||||
use edn::{
|
||||
InternSet,
|
||||
PlainSymbol,
|
||||
ValueRc,
|
||||
};
|
||||
|
||||
use mentat_core::intern_set::InternSet;
|
||||
use mentat_core::util::Either;
|
||||
|
||||
use mentat_db::{
|
||||
TxReport,
|
||||
};
|
||||
|
||||
use mentat_db::internal_types::{
|
||||
KnownEntidOr,
|
||||
TempIdHandle,
|
||||
Term,
|
||||
TermWithTempIds,
|
||||
TypedValueOr,
|
||||
};
|
||||
|
||||
use edn::entities::{
|
||||
AttributePlace,
|
||||
Entity,
|
||||
EntityPlace,
|
||||
LookupRef,
|
||||
OpType,
|
||||
TempId,
|
||||
TxFunction,
|
||||
ValuePlace,
|
||||
};
|
||||
|
||||
use mentat_core::{
|
||||
TxReport,
|
||||
TypedValue,
|
||||
};
|
||||
|
||||
use conn::{
|
||||
|
@ -85,66 +78,65 @@ use conn::{
|
|||
};
|
||||
|
||||
use errors::{
|
||||
MentatError,
|
||||
Result,
|
||||
};
|
||||
|
||||
pub type Terms = (Vec<TermWithTempIds>, InternSet<TempId>);
|
||||
pub type Terms = (Vec<Entity<TypedValue>>, InternSet<TempId>);
|
||||
|
||||
pub struct TermBuilder {
|
||||
tempids: InternSet<TempId>,
|
||||
terms: Vec<TermWithTempIds>,
|
||||
terms: Vec<Entity<TypedValue>>,
|
||||
}
|
||||
|
||||
pub struct EntityBuilder<T: BuildTerms + Sized> {
|
||||
builder: T,
|
||||
entity: KnownEntidOr<TempIdHandle>,
|
||||
entity: EntityPlace<TypedValue>,
|
||||
}
|
||||
|
||||
pub trait BuildTerms where Self: Sized {
|
||||
fn named_tempid(&mut self, name: String) -> TempIdHandle;
|
||||
fn named_tempid<I>(&mut self, name: I) -> ValueRc<TempId> where I: Into<String>;
|
||||
fn describe_tempid(self, name: &str) -> EntityBuilder<Self>;
|
||||
fn describe<E>(self, entity: E) -> EntityBuilder<Self> where E: IntoThing<KnownEntidOr<TempIdHandle>>;
|
||||
fn add<E, V>(&mut self, e: E, a: KnownEntid, v: V) -> Result<()>
|
||||
where E: IntoThing<KnownEntidOr<TempIdHandle>>,
|
||||
V: IntoThing<TypedValueOr<TempIdHandle>>;
|
||||
fn retract<E, V>(&mut self, e: E, a: KnownEntid, v: V) -> Result<()>
|
||||
where E: IntoThing<KnownEntidOr<TempIdHandle>>,
|
||||
V: IntoThing<TypedValueOr<TempIdHandle>>;
|
||||
fn describe<E>(self, entity: E) -> EntityBuilder<Self> where E: Into<EntityPlace<TypedValue>>;
|
||||
fn add<E, A, V>(&mut self, e: E, a: A, v: V) -> Result<()>
|
||||
where E: Into<EntityPlace<TypedValue>>,
|
||||
A: Into<AttributePlace>,
|
||||
V: Into<ValuePlace<TypedValue>>;
|
||||
fn retract<E, A, V>(&mut self, e: E, a: A, v: V) -> Result<()>
|
||||
where E: Into<EntityPlace<TypedValue>>,
|
||||
A: Into<AttributePlace>,
|
||||
V: Into<ValuePlace<TypedValue>>;
|
||||
}
|
||||
|
||||
impl BuildTerms for TermBuilder {
|
||||
fn named_tempid(&mut self, name: String) -> TempIdHandle {
|
||||
self.tempids.intern(TempId::External(name))
|
||||
fn named_tempid<I>(&mut self, name: I) -> ValueRc<TempId> where I: Into<String> {
|
||||
self.tempids.intern(TempId::External(name.into()))
|
||||
}
|
||||
|
||||
fn describe_tempid(mut self, name: &str) -> EntityBuilder<Self> {
|
||||
let e = self.named_tempid(name.into());
|
||||
let e = self.named_tempid(name);
|
||||
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 {
|
||||
builder: self,
|
||||
entity: entity.into_thing(),
|
||||
entity: entity.into(),
|
||||
}
|
||||
}
|
||||
|
||||
fn add<E, V>(&mut self, e: E, a: KnownEntid, v: V) -> Result<()>
|
||||
where E: IntoThing<KnownEntidOr<TempIdHandle>>,
|
||||
V: IntoThing<TypedValueOr<TempIdHandle>> {
|
||||
let e = e.into_thing();
|
||||
let v = v.into_thing();
|
||||
self.terms.push(Term::AddOrRetract(OpType::Add, e, a.into(), v));
|
||||
fn add<E, A, V>(&mut self, e: E, a: A, v: V) -> Result<()>
|
||||
where E: Into<EntityPlace<TypedValue>>,
|
||||
A: Into<AttributePlace>,
|
||||
V: Into<ValuePlace<TypedValue>> {
|
||||
self.terms.push(Entity::AddOrRetract { op: OpType::Add, e: e.into(), a: a.into(), v: v.into() });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn retract<E, V>(&mut self, e: E, a: KnownEntid, v: V) -> Result<()>
|
||||
where E: IntoThing<KnownEntidOr<TempIdHandle>>,
|
||||
V: IntoThing<TypedValueOr<TempIdHandle>> {
|
||||
let e = e.into_thing();
|
||||
let v = v.into_thing();
|
||||
self.terms.push(Term::AddOrRetract(OpType::Retract, e, a.into(), v));
|
||||
fn retract<E, A, V>(&mut self, e: E, a: A, v: V) -> Result<()>
|
||||
where E: Into<EntityPlace<TypedValue>>,
|
||||
A: Into<AttributePlace>,
|
||||
V: Into<ValuePlace<TypedValue>> {
|
||||
self.terms.push(Entity::AddOrRetract { op: OpType::Retract, e: e.into(), a: a.into(), v: v.into() });
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -166,23 +158,35 @@ impl TermBuilder {
|
|||
}
|
||||
|
||||
#[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))
|
||||
}
|
||||
|
||||
pub fn lookup_ref<A, V>(a: A, v: V) -> LookupRef<TypedValue>
|
||||
where A: Into<AttributePlace>,
|
||||
V: Into<TypedValue> {
|
||||
LookupRef { a: a.into(), v: v.into() }
|
||||
}
|
||||
|
||||
pub fn tx_function(op: &str) -> TxFunction {
|
||||
TxFunction { op: PlainSymbol::plain(op) }
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
pub fn add<V>(&mut self, a: KnownEntid, v: V) -> Result<()>
|
||||
where V: IntoThing<TypedValueOr<TempIdHandle>> {
|
||||
pub fn add<A, V>(&mut self, a: A, v: V) -> Result<()>
|
||||
where A: Into<AttributePlace>,
|
||||
V: Into<ValuePlace<TypedValue>> {
|
||||
self.builder.add(self.entity.clone(), a, v)
|
||||
}
|
||||
|
||||
pub fn retract<V>(&mut self, a: KnownEntid, v: V) -> Result<()>
|
||||
where V: IntoThing<TypedValueOr<TempIdHandle>> {
|
||||
pub fn retract<A, V>(&mut self, a: A, v: V) -> Result<()>
|
||||
where A: Into<AttributePlace>,
|
||||
V: Into<ValuePlace<TypedValue>> {
|
||||
self.builder.retract(self.entity.clone(), a, v)
|
||||
}
|
||||
}
|
||||
|
@ -207,8 +211,8 @@ impl<'a, 'c> InProgressBuilder<'a, 'c> {
|
|||
let mut in_progress = self.in_progress;
|
||||
let result = self.builder
|
||||
.build()
|
||||
.and_then(|(terms, tempid_set)| {
|
||||
in_progress.transact_terms(terms, tempid_set)
|
||||
.and_then(|(terms, _tempid_set)| {
|
||||
in_progress.transact_entities(terms)
|
||||
});
|
||||
(in_progress, result)
|
||||
}
|
||||
|
@ -226,79 +230,38 @@ impl<'a, 'c> InProgressBuilder<'a, 'c> {
|
|||
}
|
||||
|
||||
impl<'a, 'c> BuildTerms for InProgressBuilder<'a, 'c> {
|
||||
fn named_tempid(&mut self, name: String) -> TempIdHandle {
|
||||
fn named_tempid<I>(&mut self, name: I) -> ValueRc<TempId> where I: Into<String> {
|
||||
self.builder.named_tempid(name)
|
||||
}
|
||||
|
||||
fn describe_tempid(mut self, name: &str) -> EntityBuilder<InProgressBuilder<'a, 'c>> {
|
||||
let e = self.builder.named_tempid(name.into());
|
||||
let e = self.builder.named_tempid(name.to_string());
|
||||
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 {
|
||||
builder: self,
|
||||
entity: entity.into_thing(),
|
||||
entity: entity.into(),
|
||||
}
|
||||
}
|
||||
|
||||
fn add<E, V>(&mut self, e: E, a: KnownEntid, v: V) -> Result<()>
|
||||
where E: IntoThing<KnownEntidOr<TempIdHandle>>,
|
||||
V: IntoThing<TypedValueOr<TempIdHandle>> {
|
||||
fn add<E, A, V>(&mut self, e: E, a: A, v: V) -> Result<()>
|
||||
where E: Into<EntityPlace<TypedValue>>,
|
||||
A: Into<AttributePlace>,
|
||||
V: Into<ValuePlace<TypedValue>> {
|
||||
self.builder.add(e, a, v)
|
||||
}
|
||||
|
||||
fn retract<E, V>(&mut self, e: E, a: KnownEntid, v: V) -> Result<()>
|
||||
where E: IntoThing<KnownEntidOr<TempIdHandle>>,
|
||||
V: IntoThing<TypedValueOr<TempIdHandle>> {
|
||||
fn retract<E, A, V>(&mut self, e: E, a: A, v: V) -> Result<()>
|
||||
where E: Into<EntityPlace<TypedValue>>,
|
||||
A: Into<AttributePlace>,
|
||||
V: Into<ValuePlace<TypedValue>> {
|
||||
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>> {
|
||||
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
|
||||
/// `InProgress`. This method _always_ returns the `InProgress` -- failure doesn't
|
||||
/// imply an automatic rollback.
|
||||
|
@ -313,69 +276,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)]
|
||||
mod testing {
|
||||
extern crate mentat_db;
|
||||
|
@ -384,9 +284,11 @@ mod testing {
|
|||
Conn,
|
||||
Entid,
|
||||
HasSchema,
|
||||
KnownEntid,
|
||||
MentatError,
|
||||
Queryable,
|
||||
TypedValue,
|
||||
TxReport,
|
||||
TypedValue,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
@ -399,7 +301,7 @@ mod testing {
|
|||
#[test]
|
||||
fn test_entity_builder_bogus_entids() {
|
||||
let mut builder = TermBuilder::new();
|
||||
let e = builder.named_tempid("x".into());
|
||||
let e = builder.named_tempid("x");
|
||||
let a1 = fake_known_entid(37); // :db/doc
|
||||
let a2 = fake_known_entid(999);
|
||||
let v = TypedValue::typed_string("Some attribute");
|
||||
|
@ -419,7 +321,7 @@ mod testing {
|
|||
let mut in_progress = conn.begin_transaction(&mut sqlite).expect("begun successfully");
|
||||
|
||||
// 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) => {
|
||||
assert_eq!(e.kind(), mentat_db::DbErrorKind::UnrecognizedEntid(999));
|
||||
},
|
||||
|
@ -451,10 +353,10 @@ mod testing {
|
|||
let a_many = in_progress.get_entid(&kw!(:foo/many)).expect(":foo/many");
|
||||
|
||||
let mut builder = in_progress.builder();
|
||||
let e_x = builder.named_tempid("x".into());
|
||||
let e_x = builder.named_tempid("x");
|
||||
let v_many_1 = TypedValue::typed_string("Some 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.commit().expect("commit succeeded");
|
||||
}
|
||||
|
@ -489,8 +391,8 @@ mod testing {
|
|||
// Scoped borrow of in_progress.
|
||||
{
|
||||
let mut builder = TermBuilder::new();
|
||||
let e_x = builder.named_tempid("x".into());
|
||||
let e_y = builder.named_tempid("y".into());
|
||||
let e_x = builder.named_tempid("x");
|
||||
let e_y = builder.named_tempid("y");
|
||||
let a_ref = in_progress.get_entid(&foo_ref).expect(":foo/ref");
|
||||
let a_one = in_progress.get_entid(&foo_one).expect(":foo/one");
|
||||
let a_many = in_progress.get_entid(&foo_many).expect(":foo/many");
|
||||
|
@ -508,7 +410,7 @@ mod testing {
|
|||
assert_eq!(tempids.len(), 2);
|
||||
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 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"),
|
||||
|
|
|
@ -41,6 +41,7 @@ pub use mentat_core::{
|
|||
Keyword,
|
||||
Schema,
|
||||
Binding,
|
||||
TxReport,
|
||||
TypedValue,
|
||||
Uuid,
|
||||
Utc,
|
||||
|
@ -56,7 +57,6 @@ pub use mentat_db::{
|
|||
DB_SCHEMA_CORE,
|
||||
AttributeSet,
|
||||
TxObserver,
|
||||
TxReport,
|
||||
new_connection,
|
||||
};
|
||||
|
||||
|
|
16
src/store.rs
16
src/store.rs
|
@ -30,12 +30,12 @@ use mentat_core::{
|
|||
Entid,
|
||||
Keyword,
|
||||
StructuredMap,
|
||||
TxReport,
|
||||
TypedValue,
|
||||
ValueRc,
|
||||
};
|
||||
use mentat_db::{
|
||||
TxObserver,
|
||||
TxReport,
|
||||
};
|
||||
|
||||
use mentat_tolstoy::Syncer;
|
||||
|
@ -607,12 +607,12 @@ mod tests {
|
|||
let name = format!("todo{}", i);
|
||||
let uuid = Uuid::new_v4();
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
}
|
||||
let (ip, r) = builder.transact();
|
||||
|
@ -622,8 +622,8 @@ mod tests {
|
|||
in_progress = ip;
|
||||
}
|
||||
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(&kw!(:label/color), TypedValue::typed_string("blue")).expect("Expected added color");
|
||||
builder.add(kw!(:label/name), TypedValue::typed_string("Label 1")).expect("Expected added name");
|
||||
builder.add(kw!(:label/color), TypedValue::typed_string("blue")).expect("Expected added color");
|
||||
builder.commit().expect("expect transaction to occur");
|
||||
}
|
||||
|
||||
|
@ -678,8 +678,8 @@ mod tests {
|
|||
for i in 0..3 {
|
||||
let name = format!("label{}", i);
|
||||
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(&kw!(:label/color), TypedValue::typed_string("blue")).expect("Expected added color");
|
||||
builder.add(kw!(:label/name), TypedValue::typed_string(&name)).expect("Expected added name");
|
||||
builder.add(kw!(:label/color), TypedValue::typed_string("blue")).expect("Expected added color");
|
||||
let (ip, _) = builder.transact();
|
||||
in_progress = ip;
|
||||
}
|
||||
|
|
|
@ -812,14 +812,14 @@ impl VocabularySource for SimpleVocabularySource {
|
|||
impl<'a, 'c> VocabularyMechanics for InProgress<'a, 'c> {
|
||||
/// Turn the vocabulary into datoms, transact them, and on success return the outcome.
|
||||
fn install_vocabulary(&mut self, definition: &Definition) -> Result<VocabularyOutcome> {
|
||||
let (terms, tempids) = definition.description(self)?;
|
||||
self.transact_terms(terms, tempids)?;
|
||||
let (terms, _tempids) = definition.description(self)?;
|
||||
self.transact_entities(terms)?;
|
||||
Ok(VocabularyOutcome::Installed)
|
||||
}
|
||||
|
||||
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)?;
|
||||
self.transact_terms(terms, tempids)?;
|
||||
let (terms, _tempids) = definition.description_for_attributes(&attributes, self, None)?;
|
||||
self.transact_entities(terms)?;
|
||||
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
|
||||
// to elide duplicate datoms.
|
||||
let (terms, tempids) = definition.description_diff(self, &from_version)?;
|
||||
self.transact_terms(terms, tempids)?;
|
||||
let (terms, _tempids) = definition.description_diff(self, &from_version)?;
|
||||
self.transact_entities(terms)?;
|
||||
|
||||
definition.post(self, &from_version)?;
|
||||
Ok(VocabularyOutcome::Upgraded)
|
||||
|
|
Loading…
Reference in a new issue