-
-
Notifications
You must be signed in to change notification settings - Fork 311
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Upserts fail when tx-data is passed as vector rather than map #99
Comments
Actually, there is an issue with the map version as well: It seems that if the tempid is resolved via the (let [tid (ds/tempid :db.part/user)]
(ds/transact! conn [{:db/id tid :person/name "foo"}
{:db/id tid :extra "value"}])) works fine, but if you try to assert other fields before the (let [tid (ds/tempid :db.part/user)]
(ds/transact! conn [{:db/id tid :extra "value"}
{:db/id tid :person/name "foo"}]))
;; 1. Unhandled clojure.lang.ExceptionInfo
;; Cannot resolve upsert for {:db/id 2, :person/name "foo"}: {:db/id
;; 2, :person/name "foo"} conflicts with existing #datascript/Datom [1
;; :person/name "foo" 536870913 true] |
It looks like you're going down the same path I did in this issue: #76 Are you also trying to sync datoms from a datomic db to a datascript db? The workaround I'm using is to separate the datoms with unique attributes and transact those (in map form, of course) first. Then take the tempids from the tx-report and reduce through the rest of the datoms, replacing tempids with the ids they resolved to and building up maps from the datoms. It looks something like (I haven't actually run this): (def datoms [#datom[tid :extra "value" tx0 true]
#datom[tid :person/name "foo" tx0 true]])
(let [{adds true retracts false} (group-by :added datoms)
{unique true rest-datoms false} (group-by unique-attr? adds)
;; first transact unique ids resolve tempids,
;; for our example, will look like [{:db/id tid :person/name "foo"}]
{:keys [tempids]} (d/transact! db-conn (map (fn [d]
(assoc {:db/id (:e d)}
(:a d) (:v d)))
unique))]
;; Replace resolved tempids in the 2nd transaction
;; For our example, It will look something like [{:db/id 1 :extra "value"}]
(d/transact! db-conn (concat retracts
(vals (reduce (fn [acc d]
(update acc (:e d) (fn [m]
(assoc m
:db/id (get tempids (:e d) (:e d))
(:a d) (:v d)))))
{} rest-datoms)))))
I think that will probably fail if there are more than 1 unique attrs for a single entity. |
@dwwoelfel Ah, thanks for pointing out the related issue! I'm not trying to sync datomic and datascript --- just persist a subset of datascript datoms to disk and then load them back up again. Based on @tonsky's comments in #76 it seems like there's a deliberate difference between datascript and datomic in this case, so I'll just need to add a special case to save/load entities with db.unique attributes. Closing this issue as a duplicate of #76. |
With
DataScript's behavior:
differs from Datomic's
Currently all of the tests in
datascript/test/datascript/test/upsert.cljc
use the map version only.As far as I can tell, semantically the vector version should work as well.
The text was updated successfully, but these errors were encountered: