ribelo / doxa

The Unlicense
232 stars 8 forks source link

inconsistent type returned by pull join depending on cardinality #16

Closed stevebuik closed 3 years ago

stevebuik commented 3 years ago
(let [db (dx/create-dx [{:db/id 1 :name "ivan" :cars [{:db/id 10 :name "tesla"}
                                                        {:db/id 11 :name "ferrari"}]}
                          {:db/id 2 :name "petr" :cars [{:db/id 10 :name "peugot"}]}
                          {:db/id 3 :name "mike" :cars []}])]
    [; expected result
     (:cars (dx/pull db [:name {:cars [:name]}] [:db/id 1]))
     ; unexpected result
     (:cars (dx/pull db [:name {:cars [:name]}] [:db/id 2]))])

When there is a single entity, pull returns the entity without the vector. Is this intentional or a bug? This is different from pull in other impls.

I can workaround it but just want to know that it's intentional.

ribelo commented 3 years ago

It is identical to other implementations. The tests were copied from datascript, which, if the description is trustworthy, is compatible with datomic in this respect.

https://github.com/tonsky/datascript/blob/master/test/datascript/test/pull_api.cljc#L198

stevebuik commented 3 years ago

I'm not sure that's true. In Datascript, you can mark a ref attribute as plural using

{:db/type :db.type/ref :db/cardinality :db.cardinality/many}

and then pull always returns a vector.

I use Datomic Cloud and the same is true there for "many" attributes.

Does this concept exist in a Doxa db?

stevebuik commented 3 years ago

none of the tests you link to show this particular example. or am I missing something?

ribelo commented 3 years ago

Could you paste a sample datascript code so I can check? Maybe I don't know how to do something. If it is as you say then I will gladly correct it to make it consistent.

stevebuik commented 3 years ago

no probs. does this make it clear?

(do
  (require '[datascript.core :as d])
  (let [schema {:cars {:db/type        :db.type/ref
                       :db/cardinality :db.cardinality/many}}
        db (d/create-conn schema)]
    ; try this with no schema and it will reject the cars refs
    (d/transact! db [{:db/id 1
                      :name  "Rafal"
                      :cars  [20]}

                     {:db/id 2
                      :name  "Steve"
                      :cars  [20 21]}

                     {:db/id 20
                      :make  "Ferrari"}
                     {:db/id 21
                      :make  "Tesla"}])

    {:single-child (d/pull @db [:name {:cars     [:make]
                                       :projects [:name]}] 1)
     :n-child      (d/pull @db [:name {:cars     [:make]
                                       :projects [:name]}] 2)}))
stevebuik commented 3 years ago

here's a test for it...

(t/deftest gh-16
  ; https://github.com/ribelo/doxa/issues/16
  (let [db (dx/create-dx [{:db/id 1 :name "ivan" :cars [{:db/id 10 :name "tesla"}
                                                        {:db/id 11 :name "ferrari"}]}
                          {:db/id 2 :name "petr" :cars [{:db/id 10 :name "peugot"}]}
                          {:db/id 3 :name "mike" :cars []}])]
    (t/is (vector? (:cars (dx/pull db [:name {:cars [:name]}] [:db/id 1])))
          "pull returns vector when N entities in join")
    (t/is (vector? (:cars (dx/pull db [:name {:cars [:name]}] [:db/id 2])))
          "pull returns vector when 1 entity in join")))
stevebuik commented 3 years ago

fix validated in my apps. closing