Fork me on GitHub
#datascript
<
2022-08-30
>
Drew Verlee20:08:41

I'm trying to understand what this error is telling me i need to do

;; => #error {:message "Conflicting upsert: \"-12\" resolves both to 4 and 25", :data {:error :transact/upsert}}
-12 is a temporary id, are 4 and 25 supposed to be entity ids?

Drew Verlee20:08:08

is it saying that -12 has matched two entities that it should be associated with?

Drew Verlee20:08:16

yeah, that would seem to be the case...

Drew Verlee20:08:18

I was hoping that two entities with different tempids but a shared unique identity attribute (e.g server.db/id would merge, rather then confict.

;; => [[:db/add "-12" :user/roles :sponsor 536870913 true]
  ;;     [:db/add "-12" :centriq.sync.remote.server.db/id "316659348808228"]]

  ;; => [[:db/add "-4" :user/roles :admin 536870913 true]
  ;;     [:db/add "-4" :centriq.sync.remote.server.db/id "316659348808228"]]

  ;; => [[:db/add
  ;;      "-25"
  ;;      :user/roles
  ;;      :centriq-web.data-browser/edit-field
  ;;      536870913
  ;;      true]
  ;;     [:db/add "-25" :centriq.sync.remote.server.db/id "316659348808228"]]

Drew Verlee20:08:18

i guess another way to do this is to just map the server ids to shorter ids on the client. then map back when i send to the server.

Drew Verlee20:08:46

Though, if i just transact that information by itself, not as part of the much larger transaction that throws, it doesnt throw.

(def a-tx (concat
             [[:db/add "-12" :user/roles :sponsor 536870913 true]
              [:db/add "-12" :centriq.sync.remote.server.db/id "316659348808228"]]

             [[:db/add "-4" :user/roles :admin 536870913 true]
              [:db/add "-4" :centriq.sync.remote.server.db/id "316659348808228"]]

             [[:db/add
               "-25"
               :user/roles
               :centriq-web.data-browser/edit-field
               536870913
               true]
              [:db/add "-25" :centriq.sync.remote.server.db/id "316659348808228"]]))

  a-tx

  (def after
    (d/transact! connection
                 a-tx))

  (:tx-data after)
  ;; results...
    [#datascript/Datom [1 :user/roles :sponsor 536870914 true]
     #datascript/Datom [1 :centriq.sync.remote.server.db/id "316659348808228" 536870914 true]
     #datascript/Datom [1 :user/roles :admin 536870914 true]
     #datascript/Datom [1 :user/roles :centriq-web.data-browser/edit-field 536870914 true]]

Drew Verlee20:08:32

if the temp ids are out of order then it fails ...

(def a-tx (concat
             [[:db/add "-12" :user/roles :sponsor 536870913 true]
               ]
     
             [[:db/add "-4" :user/roles :admin 536870913 true]
              [:db/add "-12" :centriq.sync.remote.server.db/id "316659348808228"] ;;<--- out of order
              [:db/add "-4" :centriq.sync.remote.server.db/id "316659348808228"]]

             [[:db/add
               "-25"
               :user/roles
               :centriq-web.data-browser/edit-field
               536870913
               true]
              [:db/add "-25" :centriq.sync.remote.server.db/id "316659348808228"]]))

Drew Verlee21:08:09

if i sort them, it works though. so ok, i can do that 🙂

seepel21:08:08

I'm curious what you mean by sorting them, do you mean to say that this works?

[[:db/add "-4" :user/roles :admin 536870913 true]
 [:db/add "-4" :centriq.sync.remote.server.db/id "316659348808228"]
 [:db/add "-12" :user/roles :sponsor 536870913 true]
 [:db/add "-12" :centriq.sync.remote.server.db/id "316659348808228"]]
but this doesn't?
[[:db/add "-12" :user/roles :sponsor 536870913 true]
 [:db/add "-12" :centriq.sync.remote.server.db/id "316659348808228"]
 [:db/add "-4" :user/roles :admin 536870913 true]
 [:db/add "-4" :centriq.sync.remote.server.db/id "316659348808228"]]

seepel21:08:02

For what it's worth, the way I am handling this is that if I am trying to send datoms to the client from the server, I loop through the datoms collecting a mapping of tempid to serverid. What I send to the client is to first set the :server/id for the set of tempids that I'm working with, then in the datoms themselves I use a lookup by :server/id.

(datoms->client 
  [[316659348808228 :user/roles :admin 536870913 true]
   [316659348808228 :user/roles :sponsor 536870913 true]])
=> [[:db/add -1 :server/id 316659348808228]
    [:db/add [:server/id 316659348808228] :user/roles :admin 536870913 true]
    [:db/add [:server/id 316659348808228] :user/roles :sponsor 536870913 true]] 
I also need to make sure I look at the schema to see if I also need to convert any values that are :db.type/ref
[:db/add [:server/id 316659348808228] :some/ref [:server/id 316659348808229]]
Also note that a ref could appear in a tuple, I've been avoiding using tuples for anything other than uniqueness because I haven't sorted out how that should work in datascript yet.

seepel21:08:27

Btw, I use the lookup because you can't retract a tempid like this

[:db/retract -1 :user/roles]
Lots of details 🙂

Drew Verlee22:08:26

@U03NXD9TGBD When i said "out of order" i should have said "not grouped" (as it's more specific). So "1 1 2" will work but not "1 2 1". I think i was rather tried when i typed that message, and the error was eating up 90% of my brain.

seepel00:09:41

> When i said "out of order" i should have said "not grouped" (as it's more specific). So "1 1 2" will work but not "1 2 1". So both of my examples work? > I think i was rather tried when i typed that message, and the error was eating up 90% of my brain. Oh yeah, I've been there 🙂

Drew Verlee00:09:11

Yes, i believe both would work. But i didn't check.

seepel01:09:59

Got it, thanks! I'm always wondering what kind of idiosyncrasies I'm going to find between datascript and datomic.