Skip to content
This repository was archived by the owner on Sep 12, 2018. It is now read-only.
This repository was archived by the owner on Sep 12, 2018. It is now read-only.

Proposal: in-query retract and assert #631

@rnewman

Description

@rnewman

A common pattern I've encountered is:

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");
        builder.retract(e, link_title, obsolete)?;
    }
    ip.transact_builder(builder)?;
}

That is: query to build up retractions and/or assertions, then transact those.

Datomic follows this model easily: it's loosely typed, data is local and in memory, etc. etc.

It's slightly less comfortable in Rust because of the rigid type system: we can't easily make builder ergonomic, and the caller needs to do some ritual (into_rel_result, consuming the results, etc.) to make this happen.

It's likely to be even more uncomfortable, and perhaps a little slow, from other languages.

We might instead choose to borrow from SPARQL UPDATE and extend our syntax to do this inline:

PREFIX foaf:  <http://xmlns.com/foaf/0.1/>

WITH <http://example/addresses>
DELETE { ?person foaf:givenName 'Bill' }
INSERT { ?person foaf:givenName 'William' }
WHERE
  { ?person foaf:givenName 'Bill'
  } 

which for Mentat might look exactly like a :find query with different operands:

[:retract (?person :person/name "Bill")
 :assert (?person :person/name "William")
 :where [?person :person/name "Bill"]]

This could be evaluated in one of two ways:

  • As a special kind of projection that does the ritual consume/build/transact work for you. This is expensive — values will be pulled into memory, collected, then serialized for SQL and transacted — but it's relatively little work.
  • By translation into SQL. In part this will encode some of the work the transactor already does. More development work, but more production-grade.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-queryIssues or requests for query capabilities.A-transactIssues or requests in the transactor.discussionThis issue captures useful discussion or knowledge.enhancement

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions