Lookup ref upsert

I think this is well defined

[:db/add [:neighborhood/name "Foo"] :neighborhood/district 17592186045521]

In the case where [:neighborhood/name "Foo"] does not resolve to an entity, I think the server can infer and assert an additional statement like this:

[[:db/add "datomic.tempid/1" :neighborhood/name "Foo"]
 [:db/add "datomic.tempid/1" :neighborhood/district 17592186045521]]

We are considering implementing this from application space in Hyperfiddle (by wrapping d/with and d/transact), otherwise userspace needs to be aware of and handle this case.

Thoughts?

2 Likes

Actually the present behavior causes a difficult problem when combined with d/with.

  1. Craft a tx with a new entity by :db.unique/identity, e.g. [:db/add "datomic.tempid/1" :neighborhood/name "Foo"]
  2. “Stage” the tx through d/with
  3. From the speculative dbval, query [:find [(pull ?e [#_:db/id :neighborhood/name]) ...] :where [?e :neighborhood/name]] and note that :db/id was not pulled.
  4. To stage further edits to this entity, we must be able to identify it in a statement, but the lookup ref is not valid yet and must refer by tempid.
  5. The tempid is present in the d/with :tempids map, but the userland query did not pull :db/id so this is not knowable by the system whether the lookup ref is valid yet or not.

But only in the d/with case. The d/transact case is unaffected. I believe this may be a semantic divergence between dbvals returned by d/with vs d/transact.