Struct mentat::vocabulary::Definition [] [src]

pub struct Definition {
    pub name: Keyword,
    pub version: Version,
    pub attributes: Vec<(Keyword, Attribute)>,
    pub pre: fn(_: &mut InProgress, _: &Vocabulary) -> Result<()>,
    pub post: fn(_: &mut InProgress, _: &Vocabulary) -> Result<()>,
}

A definition of an attribute that is independent of a particular store.

Attribute instances not only aren't named, but don't even have entids.

We need two kinds of structure: an abstract definition of a vocabulary in terms of names, and a concrete instance of a vocabulary in a particular store.

Definition is the former, and Vocabulary is the latter.

Note that, because it's possible to 'flesh out' a vocabulary with attributes without bumping its version number, we need to track the attributes that the application cares about — it's not enough to know the name and version. Indeed, we even care about the details of each attribute, because that's how we'll detect errors.

Definition includes two additional fields: functions to run if this vocabulary is being upgraded. pre and post are run before and after the definition is transacted against the store. Each is called with the existing Vocabulary instance so that they can do version checks or employ more fine-grained logic.

Fields

Methods

impl Definition
[src]

#[macro_use(kw)]
extern crate mentat;

use mentat::{
    HasSchema,
    IntoResult,
    Queryable,
    Store,
    TypedValue,
    ValueType,
};

use mentat::entity_builder::{
    BuildTerms,
    TermBuilder,
};

use mentat::vocabulary;
use mentat::vocabulary::{
    AttributeBuilder,
    Definition,
    HasVocabularies,
    VersionedStore,
};

fn main() {
    let mut store = Store::open("").expect("connected");
    let mut in_progress = store.begin_transaction().expect("began transaction");

    // Make sure the core vocabulary exists.
    in_progress.verify_core_schema().expect("verified");

    // Make sure our vocabulary is installed, and install if necessary.
    in_progress.ensure_vocabulary(&Definition {
        name: kw!(:example/links),
        version: 2,
        attributes: vec![
            (kw!(:link/title),
             AttributeBuilder::helpful()
               .value_type(ValueType::String)
               .multival(false)
               .fulltext(true)
               .build()),
        ],
        pre: |ip, from| {
            // Version one allowed multiple titles; version two
            // doesn't. Retract any duplicates we find.
            if from.version < 2 {
                let link_title = ip.get_entid(&kw!(:link/title)).unwrap();

                let results = ip.q_once(r#"
                    [:find ?e ?t2
                     :where [?e :link/title ?t1]
                            [?e :link/title ?t2]
                            [(unpermute ?t1 ?t2)]]
                "#, None).into_rel_result()?;

                if !results.is_empty() {
                    let mut builder = TermBuilder::new();
                    for row in results.into_iter() {
                        let mut r = row.into_iter();
                        let e = r.next().and_then(|e| e.into_known_entid()).expect("entity");
                        let obsolete = r.next().expect("value").val().expect("typed value");
                        builder.retract(e, link_title, obsolete)?;
                    }
                    ip.transact_builder(builder)?;
                }
            }
            Ok(())
        },
        post: |_ip, from| {
            println!("We migrated :example/links from version {}", from.version);
            Ok(())
        },
    }).expect("ensured");

    // Now we can do stuff.
    in_progress.transact("[{:link/title \"Title\"}]").expect("transacts");
    in_progress.commit().expect("commits");
}

Trait Implementations

impl Clone for Definition
[src]

Returns a copy of the value. Read more

Performs copy-assignment from source. Read more

Auto Trait Implementations

impl Send for Definition

impl Sync for Definition