Skip to content

Instantly share code, notes, and snippets.

@katox
Last active July 20, 2018 10:25
Show Gist options
  • Save katox/8865082 to your computer and use it in GitHub Desktop.
Save katox/8865082 to your computer and use it in GitHub Desktop.
Compare-and-set with datomic upsert
;; insert test case within project https://github.com/Datomic/day-of-datomic into 'lein repl'
(use '[datomic.api :only [q db] :as d])
(use 'clojure.pprint)
(def uri "datomic:mem://seattle")
(d/create-database uri)
(def conn (d/connect uri))
(def schema-tx (read-string (slurp "samples/seattle/seattle-schema.edn")))
@(d/transact conn schema-tx)
(defn nb []
(q '[:find ?e ?n ?r :in $ :where [?e :neighborhood/name ?n] [?e :neighborhood/district ?d] [?d :db/ident ?r] ]
(db conn)))
(defn fnd [name]
(q '[:find ?e ?n ?d :in $ ?n :where [?e :neighborhood/name ?n] [?e :neighborhood/district ?d]]
(db conn) name))
@(d/transact conn [{:db/id #db/id[:db.part/user -1]
:neighborhood/name "first name"
:neighborhood/district :region/n}])
@(d/transact conn [{:db/id #db/id[:db.part/user -2]
:neighborhood/name "second name"
:neighborhood/district :region/w}])
;; user=> (nb)
#{[17592186045440 "second name" :region/w] [17592186045438 "first name" :region/n]}
(def eid (ffirst (fnd "first name")))
(def old-dist (last (first (fnd "first name"))))
;; try upsert with tempid, no match
@(d/transact conn [{:db/id #db/id[:db.part/user -2]
:neighborhood/name "first name"}
[:db.fn/cas #db/id[:db.part/user -2] :neighborhood/district old-dist :region/s]])
;;=> IllegalStateExceptionInfo :db.error/cas-failed Compare failed: 17592186045429 datomic.error/state (error.clj:64)
;; user=> (nb)
#{[17592186045440 "second name" :region/w] [17592186045438 "first name" :region/n]}
;; try upsert with resolved eid, ok
@(d/transact conn [{:db/id eid
:neighborhood/name "first name"}
[:db.fn/cas eid :neighborhood/district old-dist :region/s]])
;;=> {:db-before datomic.db.Db@d86db660, :db-after datomic.db.Db@658686bc, :tx-data [#Datum{:e 13194139534337 :a 50 :v #inst "2014-02-07T15:31:49.960-00:00" :tx 13194139534337 :added true} #Datum{:e 17592186045438 :a 70 :v 17592186045433 :tx 13194139534337 :added true} #Datum{:e 17592186045438 :a 70 :v 17592186045429 :tx 13194139534337 :added false}], :tempids {}}
;; user=> (nb)
#{[17592186045438 "first name" :region/s] [17592186045440 "second name" :region/w]}
;; try upsert with tempid and cas attr set to nil, accepted!
@(d/transact conn [{:db/id #db/id[:db.part/user -100]
:neighborhood/name "first name"}
[:db.fn/cas #db/id[:db.part/user -100] :neighborhood/district nil :region/e]])
;;=> {:db-before datomic.db.Db@658686bc, :db-after datomic.db.Db@6d2c3cf7, :tx-data [#Datum{:e 13194139534338 :a 50 :v #inst "2014-02-07T15:33:49.393-00:00" :tx 13194139534338 :added true} #Datum{:e 17592186045438 :a 70 :v 17592186045431 :tx 13194139534338 :added true} #Datum{:e 17592186045438 :a 70 :v 17592186045433 :tx 13194139534338 :added false}], :tempids {-9223350046622220388 17592186045438}}
;; user=> (nb)
#{[17592186045438 "first name" :region/e] [17592186045440 "second name" :region/w]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment