Skip to content
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

Transaction / Indexing bug #376

Open
den1k opened this issue Dec 15, 2020 · 2 comments
Open

Transaction / Indexing bug #376

den1k opened this issue Dec 15, 2020 · 2 comments

Comments

@den1k
Copy link

den1k commented Dec 15, 2020

In a transaction where a map has refs and reverse-ref attributes, the ref attributes are thrown away.

This works:

(require '[datascript.core :as d])

(def db
  (d/empty-db
    {:foo/id        {:db/unique :db.unique/identity}
     :foo/relations {:db/valueType   :db.type/ref
                     :db/cardinality :db.cardinality/many}}))

(def db-with-foo
  (d/db-with
    db
    [{:foo/id        "foo1"
      :foo/relations [{:foo/id "foo2"}
                      {:foo/id "foo3"}]}]))

(comment
 (d/touch (d/entity db-with-foo [:foo/id "foo3"]))
; works!
; => {:foo/id "foo3", :db/id 3}
)

This fails for :foo/relations [{:foo/id "foo3"}] but works for the reverse :foo/_relations:

(def db-with-foo-backwards
  (d/db-with
    db
    [{:foo/id         "foo2"
      :foo/_relations [{:foo/id "foo1" :foo/relations [{:foo/id "foo3"}]}]}]))

(comment
 (d/touch (d/entity db-with-foo-backwards [:foo/id "foo3"]))
; errors!
; => #object[Error Error: Assert failed: (entity? e)] 

; relation between "foo1" and "foo2" exists
(d/touch (d/entity db-with-foo-backwards [:foo/id "foo1"])) 
 ; => {:foo/id "foo1", :foo/relations #{#:db{:id 1}}, :db/id 2}
)

Looking at the indexes of either DB we see that the relations and datoms are missing in db-with-foo-backwards:

(comment
 (:aevt db-with-foo)
; =>
;#{#datascript/Datom[1 :foo/id "foo1" 536870913 true]
;  #datascript/Datom[2 :foo/id "foo2" 536870913 true]
;  #datascript/Datom[3 :foo/id "foo3" 536870913 true] ; <-- foo3 exists!
;  #datascript/Datom[1 :foo/relations 2 536870913 true]
;  #datascript/Datom[1 :foo/relations 3 536870913 true]}
)
(comment
  (:aevt db-with-foo-backwards)
; =>
;#{#datascript/Datom[1 :foo/id "foo2" 536870913 true]
;  #datascript/Datom[2 :foo/id "foo1" 536870913 true] ; <-- foo3 and relations missing!
;  #datascript/Datom[2 :foo/relations 1 536870913 true]}
)
@den1k
Copy link
Author

den1k commented Dec 15, 2020

The common use case where this matters anytime one wants to run a pull query on one database and transact the result into another. In my case I have a backend and frontend DataScript DB. Based on the route the backend runs d/pull and sends the result to the frontend to be transacted. Since the pull result contains both forward and backward refs, this fails.

@tonsky
Copy link
Owner

tonsky commented Dec 15, 2020

Looks like a valid use-case, I’ll look into it, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants