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.
|
/// Core types defining a Mentat knowledge base.
|
||||||
mod types;
|
mod types;
|
||||||
|
mod tx_report;
|
||||||
mod value_type_set;
|
mod value_type_set;
|
||||||
mod sql_types;
|
mod sql_types;
|
||||||
|
|
||||||
|
pub use tx_report::{
|
||||||
|
TxReport,
|
||||||
|
};
|
||||||
|
|
||||||
pub use types::{
|
pub use types::{
|
||||||
Binding,
|
Binding,
|
||||||
Entid,
|
Entid,
|
||||||
|
@ -365,7 +370,6 @@ impl HasSchema for Schema {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod intern_set;
|
|
||||||
pub mod counter;
|
pub mod counter;
|
||||||
pub mod util;
|
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,
|
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.
|
||||||
|
|
19
db/src/db.rs
19
db/src/db.rs
|
@ -1119,20 +1119,22 @@ mod tests {
|
||||||
use debug;
|
use debug;
|
||||||
use errors;
|
use errors;
|
||||||
use edn;
|
use edn;
|
||||||
use mentat_core::{
|
use edn::{
|
||||||
HasSchema,
|
|
||||||
Keyword,
|
|
||||||
KnownEntid,
|
|
||||||
attribute,
|
|
||||||
};
|
|
||||||
use mentat_core::intern_set::{
|
|
||||||
InternSet,
|
InternSet,
|
||||||
};
|
};
|
||||||
use mentat_core::util::Either::*;
|
|
||||||
use edn::entities::{
|
use edn::entities::{
|
||||||
OpType,
|
OpType,
|
||||||
TempId,
|
TempId,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use mentat_core::{
|
||||||
|
HasSchema,
|
||||||
|
Keyword,
|
||||||
|
KnownEntid,
|
||||||
|
TxReport,
|
||||||
|
attribute,
|
||||||
|
};
|
||||||
|
use mentat_core::util::Either::*;
|
||||||
use rusqlite;
|
use rusqlite;
|
||||||
use std::collections::{
|
use std::collections::{
|
||||||
BTreeMap,
|
BTreeMap,
|
||||||
|
@ -1141,7 +1143,6 @@ mod tests {
|
||||||
Term,
|
Term,
|
||||||
TermWithTempIds,
|
TermWithTempIds,
|
||||||
};
|
};
|
||||||
use types::TxReport;
|
|
||||||
use tx::{
|
use tx::{
|
||||||
transact_terms,
|
transact_terms,
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,7 +17,6 @@ use std::collections::{
|
||||||
BTreeSet,
|
BTreeSet,
|
||||||
HashMap,
|
HashMap,
|
||||||
};
|
};
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use mentat_core::KnownEntid;
|
use mentat_core::KnownEntid;
|
||||||
|
|
||||||
|
@ -27,6 +26,14 @@ use edn;
|
||||||
use edn::{
|
use edn::{
|
||||||
SpannedValue,
|
SpannedValue,
|
||||||
ValueAndSpan,
|
ValueAndSpan,
|
||||||
|
ValueRc,
|
||||||
|
};
|
||||||
|
use edn::entities;
|
||||||
|
use edn::entities::{
|
||||||
|
EntityPlace,
|
||||||
|
OpType,
|
||||||
|
TempId,
|
||||||
|
TxFunction,
|
||||||
};
|
};
|
||||||
|
|
||||||
use errors;
|
use errors;
|
||||||
|
@ -47,13 +54,6 @@ use types::{
|
||||||
TypedValue,
|
TypedValue,
|
||||||
ValueType,
|
ValueType,
|
||||||
};
|
};
|
||||||
use edn::entities;
|
|
||||||
use edn::entities::{
|
|
||||||
EntityPlace,
|
|
||||||
OpType,
|
|
||||||
TempId,
|
|
||||||
TxFunction,
|
|
||||||
};
|
|
||||||
|
|
||||||
impl TransactableValue for ValueAndSpan {
|
impl TransactableValue for ValueAndSpan {
|
||||||
fn into_typed_value(self, schema: &Schema, value_type: ValueType) -> Result<TypedValue> {
|
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))
|
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) => {
|
List(ls) => {
|
||||||
let mut it = ls.iter();
|
let mut it = ls.iter();
|
||||||
match (it.next().map(|x| &x.inner), it.next(), it.next(), it.next()) {
|
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> {
|
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 {
|
match self {
|
||||||
TypedValue::Ref(x) => Ok(EntityPlace::Entid(entities::EntidOrIdent::Entid(x))),
|
TypedValue::Ref(x) => Ok(EntityPlace::Entid(entities::EntidOrIdent::Entid(x))),
|
||||||
TypedValue::Keyword(x) => Ok(EntityPlace::Entid(entities::EntidOrIdent::Ident((*x).clone()))),
|
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::Boolean(_) |
|
||||||
TypedValue::Long(_) |
|
TypedValue::Long(_) |
|
||||||
TypedValue::Double(_) |
|
TypedValue::Double(_) |
|
||||||
|
@ -134,7 +134,7 @@ impl TransactableValue for TypedValue {
|
||||||
|
|
||||||
fn as_tempid(&self) -> Option<TempId> {
|
fn as_tempid(&self) -> Option<TempId> {
|
||||||
match self {
|
match self {
|
||||||
&TypedValue::String(ref s) => Some(TempId::External((**s).clone())),
|
&TypedValue::String(ref s) => Some(TempId::External((**s).clone()).into()),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,10 +150,10 @@ use self::Either::*;
|
||||||
pub type KnownEntidOr<T> = Either<KnownEntid, T>;
|
pub type KnownEntidOr<T> = Either<KnownEntid, T>;
|
||||||
pub type TypedValueOr<T> = Either<TypedValue, 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 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
|
/// 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
|
/// 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,
|
DB,
|
||||||
PartitionMap,
|
PartitionMap,
|
||||||
TransactableValue,
|
TransactableValue,
|
||||||
TxReport,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn to_namespaced_keyword(s: &str) -> Result<symbols::Keyword> {
|
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::{
|
use std::iter::{
|
||||||
once,
|
once,
|
||||||
};
|
};
|
||||||
use std::rc::{
|
|
||||||
Rc,
|
|
||||||
};
|
|
||||||
|
|
||||||
use db;
|
use db;
|
||||||
use db::{
|
use db::{
|
||||||
|
@ -66,6 +63,7 @@ use db::{
|
||||||
PartitionMapping,
|
PartitionMapping,
|
||||||
};
|
};
|
||||||
use edn::{
|
use edn::{
|
||||||
|
InternSet,
|
||||||
Keyword,
|
Keyword,
|
||||||
};
|
};
|
||||||
use entids;
|
use entids;
|
||||||
|
@ -96,13 +94,12 @@ use mentat_core::{
|
||||||
DateTime,
|
DateTime,
|
||||||
KnownEntid,
|
KnownEntid,
|
||||||
Schema,
|
Schema,
|
||||||
|
TxReport,
|
||||||
Utc,
|
Utc,
|
||||||
attribute,
|
attribute,
|
||||||
now,
|
now,
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_core::intern_set::InternSet;
|
|
||||||
|
|
||||||
use edn::entities as entmod;
|
use edn::entities as entmod;
|
||||||
use edn::entities::{
|
use edn::entities::{
|
||||||
AttributePlace,
|
AttributePlace,
|
||||||
|
@ -123,7 +120,6 @@ use types::{
|
||||||
Entid,
|
Entid,
|
||||||
PartitionMap,
|
PartitionMap,
|
||||||
TransactableValue,
|
TransactableValue,
|
||||||
TxReport,
|
|
||||||
TypedValue,
|
TypedValue,
|
||||||
ValueType,
|
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)))
|
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
|
/// Allocate private internal tempids reserved for Mentat. Internal tempids just need to be
|
||||||
/// unique within one transaction; they should never escape a transaction.
|
/// unique within one transaction; they should never escape a transaction.
|
||||||
fn allocate_mentat_id<W: TransactableValue>(&mut self) -> entmod::EntityPlace<W> {
|
fn allocate_mentat_id<W: TransactableValue>(&mut self) -> entmod::EntityPlace<W> {
|
||||||
self.mentat_id_count += 1;
|
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>> {
|
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) => {
|
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) => {
|
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
|
// that the given value is in the attribute's value set, or (in
|
||||||
// limited cases) coerce the value into the attribute's value set.
|
// limited cases) coerce the value into the attribute's value set.
|
||||||
match v.as_tempid() {
|
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 => {
|
None => {
|
||||||
if let TypedValue::Ref(entid) = v.into_typed_value(&self.schema, ValueType::Ref)? {
|
if let TypedValue::Ref(entid) = v.into_typed_value(&self.schema, ValueType::Ref)? {
|
||||||
Ok(Either::Left(KnownEntid(entid)))
|
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)?))),
|
Ok(Either::Left(KnownEntid(self.entity_a_into_term_a(entid)?))),
|
||||||
|
|
||||||
entmod::ValuePlace::TempId(tempid) =>
|
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) =>
|
entmod::ValuePlace::LookupRef(ref lookup_ref) =>
|
||||||
Ok(Either::Right(LookupRefOrTempId::LookupRef(self.intern_lookup_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.
|
// limited cases) coerce the value into the attribute's value set.
|
||||||
if attribute.value_type == ValueType::Ref {
|
if attribute.value_type == ValueType::Ref {
|
||||||
match v.as_tempid() {
|
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)?,
|
None => v.into_typed_value(&self.schema, attribute.value_type).map(Either::Left)?,
|
||||||
}
|
}
|
||||||
} else {
|
} 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)?)),
|
Either::Left(TypedValue::Ref(in_process.entity_a_into_term_a(entid)?)),
|
||||||
|
|
||||||
entmod::ValuePlace::TempId(tempid) =>
|
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) => {
|
entmod::ValuePlace::LookupRef(ref lookup_ref) => {
|
||||||
if attribute.value_type != ValueType::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)?;
|
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.
|
// 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 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)?;
|
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.
|
// Verify that every tempid we interned either resolved or has been allocated.
|
||||||
assert_eq!(tempids.len(), tempid_set.inner.len());
|
assert_eq!(tempids.len(), tempid_set.len());
|
||||||
for tempid in &tempid_set.inner {
|
for tempid in tempid_set.iter() {
|
||||||
assert!(tempids.contains_key(&**tempid));
|
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
|
// represents a set of entids that are correspond to attributes
|
||||||
pub type AttributeSet = BTreeSet<Entid>;
|
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
|
/// 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
|
/// `TypedValue` directly for programmatic use. `TransactableValue` encapsulates the interface
|
||||||
/// value types (i.e., values in the value place) need to support to be transacted.
|
/// 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) } }
|
= "(" __ n:$(symbol_name) __ ")" { TxFunction { op: PlainSymbol::plain(n) } }
|
||||||
|
|
||||||
entity_place -> EntityPlace<ValueAndSpan>
|
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:entid { EntityPlace::Entid(v) }
|
||||||
/ v:lookup_ref { EntityPlace::LookupRef(v) }
|
/ v:lookup_ref { EntityPlace::LookupRef(v) }
|
||||||
/ v:tx_function { EntityPlace::TxFunction(v) }
|
/ v:tx_function { EntityPlace::TxFunction(v) }
|
||||||
|
|
|
@ -13,11 +13,29 @@
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
use value_rc::{
|
||||||
|
ValueRc,
|
||||||
|
};
|
||||||
|
|
||||||
use symbols::{
|
use symbols::{
|
||||||
Keyword,
|
Keyword,
|
||||||
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)]
|
||||||
|
@ -50,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 {
|
||||||
|
@ -93,7 +123,7 @@ pub enum ValuePlace<V> {
|
||||||
Entid(EntidOrIdent),
|
Entid(EntidOrIdent),
|
||||||
// We never know at parse-time whether a string is really a tempid, but we will often know when
|
// We never know at parse-time whether a string is really a tempid, but we will often know when
|
||||||
// building entities programmatically.
|
// building entities programmatically.
|
||||||
TempId(TempId),
|
TempId(ValueRc<TempId>),
|
||||||
LookupRef(LookupRef<V>),
|
LookupRef(LookupRef<V>),
|
||||||
TxFunction(TxFunction),
|
TxFunction(TxFunction),
|
||||||
Vector(Vec<ValuePlace<V>>),
|
Vector(Vec<ValuePlace<V>>),
|
||||||
|
@ -101,19 +131,103 @@ 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),
|
||||||
TempId(TempId),
|
TempId(ValueRc<TempId>),
|
||||||
LookupRef(LookupRef<V>),
|
LookupRef(LookupRef<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,
|
||||||
|
|
|
@ -12,7 +12,14 @@
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::hash::Hash;
|
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
|
/// 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
|
/// 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.
|
/// See https://en.wikipedia.org/wiki/String_interning for discussion.
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||||
pub struct InternSet<T> where T: Eq + Hash {
|
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 {
|
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.
|
/// Intern a value, providing a ref-counted handle to the interned value.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::rc::Rc;
|
/// use edn::{InternSet, ValueRc};
|
||||||
/// use mentat_core::intern_set::InternSet;
|
|
||||||
///
|
///
|
||||||
/// let mut s = InternSet::new();
|
/// let mut s = InternSet::new();
|
||||||
///
|
///
|
||||||
/// let one = "foo".to_string();
|
/// 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);
|
/// let out_one = s.intern(one);
|
||||||
/// assert_eq!(out_one, two);
|
/// assert_eq!(out_one, two);
|
||||||
|
@ -54,11 +70,11 @@ impl<T> InternSet<T> where T: Eq + Hash {
|
||||||
///
|
///
|
||||||
/// let out_two = s.intern(two);
|
/// let out_two = s.intern(two);
|
||||||
/// assert_eq!(out_one, out_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.
|
/// // assert!(&out_one.ptr_eq(&out_two)); // Nightly-only.
|
||||||
/// ```
|
/// ```
|
||||||
pub fn intern<R: Into<Rc<T>>>(&mut self, value: R) -> Rc<T> {
|
pub fn intern<R: Into<ValueRc<T>>>(&mut self, value: R) -> ValueRc<T> {
|
||||||
let key: Rc<T> = value.into();
|
let key: ValueRc<T> = value.into();
|
||||||
if self.inner.insert(key.clone()) {
|
if self.inner.insert(key.clone()) {
|
||||||
key
|
key
|
||||||
} else {
|
} else {
|
|
@ -23,6 +23,10 @@ extern crate serde;
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
|
|
||||||
pub mod entities;
|
pub mod entities;
|
||||||
|
pub mod intern_set;
|
||||||
|
pub use intern_set::{
|
||||||
|
InternSet,
|
||||||
|
};
|
||||||
// Intentionally not pub.
|
// Intentionally not pub.
|
||||||
mod namespaceable_name;
|
mod namespaceable_name;
|
||||||
pub mod query;
|
pub mod query;
|
||||||
|
|
|
@ -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
|
||||||
|
|
11
src/conn.rs
11
src/conn.rs
|
@ -41,6 +41,9 @@ use rusqlite::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use edn;
|
use edn;
|
||||||
|
use edn::{
|
||||||
|
InternSet,
|
||||||
|
};
|
||||||
|
|
||||||
use mentat_core::{
|
use mentat_core::{
|
||||||
Attribute,
|
Attribute,
|
||||||
|
@ -50,13 +53,12 @@ use mentat_core::{
|
||||||
Keyword,
|
Keyword,
|
||||||
Schema,
|
Schema,
|
||||||
StructuredMap,
|
StructuredMap,
|
||||||
|
TxReport,
|
||||||
TypedValue,
|
TypedValue,
|
||||||
ValueRc,
|
ValueRc,
|
||||||
ValueType,
|
ValueType,
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_core::intern_set::InternSet;
|
|
||||||
|
|
||||||
use mentat_db::cache::{
|
use mentat_db::cache::{
|
||||||
InProgressCacheTransactWatcher,
|
InProgressCacheTransactWatcher,
|
||||||
InProgressSQLiteAttributeCache,
|
InProgressSQLiteAttributeCache,
|
||||||
|
@ -73,7 +75,6 @@ use mentat_db::{
|
||||||
TransactWatcher,
|
TransactWatcher,
|
||||||
TxObservationService,
|
TxObservationService,
|
||||||
TxObserver,
|
TxObserver,
|
||||||
TxReport,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_db::internal_types::TermWithTempIds;
|
use mentat_db::internal_types::TermWithTempIds;
|
||||||
|
@ -401,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,34 +50,27 @@
|
||||||
//
|
//
|
||||||
// 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 mentat_core::{
|
use edn::{
|
||||||
HasSchema,
|
InternSet,
|
||||||
KnownEntid,
|
PlainSymbol,
|
||||||
Keyword,
|
ValueRc,
|
||||||
TypedValue,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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::{
|
use edn::entities::{
|
||||||
|
AttributePlace,
|
||||||
|
Entity,
|
||||||
|
EntityPlace,
|
||||||
|
LookupRef,
|
||||||
OpType,
|
OpType,
|
||||||
TempId,
|
TempId,
|
||||||
|
TxFunction,
|
||||||
|
ValuePlace,
|
||||||
|
};
|
||||||
|
|
||||||
|
use mentat_core::{
|
||||||
|
TxReport,
|
||||||
|
TypedValue,
|
||||||
};
|
};
|
||||||
|
|
||||||
use conn::{
|
use conn::{
|
||||||
|
@ -85,66 +78,65 @@ use conn::{
|
||||||
};
|
};
|
||||||
|
|
||||||
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<I>(&mut self, name: I) -> ValueRc<TempId> where I: Into<String>;
|
||||||
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<I>(&mut self, name: I) -> ValueRc<TempId> where I: Into<String> {
|
||||||
self.tempids.intern(TempId::External(name))
|
self.tempids.intern(TempId::External(name.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn describe_tempid(mut self, name: &str) -> EntityBuilder<Self> {
|
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)
|
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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,23 +158,35 @@ 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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,8 +211,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)
|
||||||
}
|
}
|
||||||
|
@ -226,79 +230,38 @@ 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<I>(&mut self, name: I) -> ValueRc<TempId> where I: Into<String> {
|
||||||
self.builder.named_tempid(name)
|
self.builder.named_tempid(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn describe_tempid(mut self, name: &str) -> EntityBuilder<InProgressBuilder<'a, 'c>> {
|
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)
|
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.
|
||||||
|
@ -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)]
|
#[cfg(test)]
|
||||||
mod testing {
|
mod testing {
|
||||||
extern crate mentat_db;
|
extern crate mentat_db;
|
||||||
|
@ -384,9 +284,11 @@ mod testing {
|
||||||
Conn,
|
Conn,
|
||||||
Entid,
|
Entid,
|
||||||
HasSchema,
|
HasSchema,
|
||||||
|
KnownEntid,
|
||||||
|
MentatError,
|
||||||
Queryable,
|
Queryable,
|
||||||
TypedValue,
|
|
||||||
TxReport,
|
TxReport,
|
||||||
|
TypedValue,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -399,7 +301,7 @@ mod testing {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_entity_builder_bogus_entids() {
|
fn test_entity_builder_bogus_entids() {
|
||||||
let mut builder = TermBuilder::new();
|
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 a1 = fake_known_entid(37); // :db/doc
|
||||||
let a2 = fake_known_entid(999);
|
let a2 = fake_known_entid(999);
|
||||||
let v = TypedValue::typed_string("Some attribute");
|
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");
|
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));
|
||||||
},
|
},
|
||||||
|
@ -451,10 +353,10 @@ mod testing {
|
||||||
let a_many = in_progress.get_entid(&kw!(:foo/many)).expect(":foo/many");
|
let a_many = in_progress.get_entid(&kw!(:foo/many)).expect(":foo/many");
|
||||||
|
|
||||||
let mut builder = in_progress.builder();
|
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_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");
|
||||||
}
|
}
|
||||||
|
@ -489,8 +391,8 @@ mod testing {
|
||||||
// Scoped borrow of in_progress.
|
// Scoped borrow of in_progress.
|
||||||
{
|
{
|
||||||
let mut builder = TermBuilder::new();
|
let mut builder = TermBuilder::new();
|
||||||
let e_x = builder.named_tempid("x".into());
|
let e_x = builder.named_tempid("x");
|
||||||
let e_y = builder.named_tempid("y".into());
|
let e_y = builder.named_tempid("y");
|
||||||
let a_ref = in_progress.get_entid(&foo_ref).expect(":foo/ref");
|
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_one = in_progress.get_entid(&foo_one).expect(":foo/one");
|
||||||
let a_many = in_progress.get_entid(&foo_many).expect(":foo/many");
|
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!(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"),
|
||||||
|
|
|
@ -41,6 +41,7 @@ pub use mentat_core::{
|
||||||
Keyword,
|
Keyword,
|
||||||
Schema,
|
Schema,
|
||||||
Binding,
|
Binding,
|
||||||
|
TxReport,
|
||||||
TypedValue,
|
TypedValue,
|
||||||
Uuid,
|
Uuid,
|
||||||
Utc,
|
Utc,
|
||||||
|
@ -56,7 +57,6 @@ pub use mentat_db::{
|
||||||
DB_SCHEMA_CORE,
|
DB_SCHEMA_CORE,
|
||||||
AttributeSet,
|
AttributeSet,
|
||||||
TxObserver,
|
TxObserver,
|
||||||
TxReport,
|
|
||||||
new_connection,
|
new_connection,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
16
src/store.rs
16
src/store.rs
|
@ -30,12 +30,12 @@ use mentat_core::{
|
||||||
Entid,
|
Entid,
|
||||||
Keyword,
|
Keyword,
|
||||||
StructuredMap,
|
StructuredMap,
|
||||||
|
TxReport,
|
||||||
TypedValue,
|
TypedValue,
|
||||||
ValueRc,
|
ValueRc,
|
||||||
};
|
};
|
||||||
use mentat_db::{
|
use mentat_db::{
|
||||||
TxObserver,
|
TxObserver,
|
||||||
TxReport,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_tolstoy::Syncer;
|
use mentat_tolstoy::Syncer;
|
||||||
|
@ -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