I just tried using :db/ensure
, but when I pull the entity, which I’ve transacted with a :db/ensure
attribute, I did get back that :db/ensure
attribute.
(ns xxx
(:require [datomic.client.api :as d]
[clojure.pprint :refer [pprint]]))
(set! *print-namespace-maps* false)
(declare conn)
(defn tx! [tx-data] (d/transact conn {:tx-data tx-data}))
(defn valid? [& [db-val eid :as args]]
(pprint args)
(pprint (d/pull db-val ['*] eid))
true)
(comment
@(def dc (d/client {:server-type :dev-local :storage-dir :mem :system "sys"}))
(def db-ref {:db-name "lab"})
(d/delete-database dc db-ref)
(d/create-database dc db-ref)
@(def conn (d/connect dc db-ref))
(tx! [{:db/ident :valid-entity :db.entity/preds `valid?}])
(tx! [{:db/ident :entity-1 :db/doc "initial value"}])
(d/pull (d/db conn) ['* {:db/ensure ['*]}] :entity-1)
; => {:db/id 92358976733258, :db/ident :entity-1, :db/doc "initial value"}
(tx! [{:db/ident :entity-1 :db/ensure :valid-entity}])
;;; ======== this is printed by the `valid?` predicate ========
;
; (#datomic.core.db.Db{:id "1c28def8-121a-4c47-9877-555abc4e0e2d", :basisT 8, :indexBasisT 0, :index-root-id nil, :asOfT nil, :sinceT nil, :raw nil}
; 92358976733258)
;
;{:db/id 92358976733258,
; :db/ident :entity-1,
; :db/doc "initial value",
; :db/ensure [{:db/id 74766790688841, :db/ident :valid-entity}]}
;=>
;{:db-before #datomic.core.db.Db{:id "1c28def8-121a-4c47-9877-555abc4e0e2d",
; :basisT 7,
; :indexBasisT 0,
; :index-root-id nil,
; :asOfT nil,
; :sinceT nil,
; :raw nil},
; :db-after #datomic.core.db.Db{:id "1c28def8-121a-4c47-9877-555abc4e0e2d",
; :basisT 8,
; :indexBasisT 0,
; :index-root-id nil,
; :asOfT nil,
; :sinceT nil,
; :raw nil},
; :tx-data [#datom[13194139533320 50 #inst"2023-07-12T06:30:04.071-00:00" 13194139533320 true]
; #datom[92358976733258 69 74766790688841 13194139533320 true]],
; :tempids {}}
(d/pull (d/db conn) ['* {:db/ensure ['*]}] :entity-1)
;=>
;{:db/id 92358976733258,
; :db/ident :entity-1,
; :db/doc "initial value",
; :db/ensure [{:db/id 74766790688841, :db/ident :valid-entity, :db.entity/preds [xxx/valid?]}]}
(tx! [{:db/ident :entity-1 :db/doc "NEW value" :db/ensure :valid-entity}])
(d/pull (d/db conn) ['* {:db/ensure ['*]}] :entity-1)
)
As we can see, there is indeed a datom for the :db/ensure
attribute (eid 69) in the transaction receipt!
According to Schema Data Reference | Datomic
:db/ensure is a virtual attribute.
It is not added in the database;
instead it triggers checks based on the named entity.
So either the docs is incorrect or the dev-local
implementation is incorrect.
Either way, I’m a bit reluctant to introduce it to production, without understanding whether I’m doing something wrong or there is a bug.