replikativ / datahike

A fast, immutable, distributed & compositional Datalog engine for everyone.
https://datahike.io
Eclipse Public License 1.0
1.62k stars 95 forks source link

[Bug]: Failure to transact value`:db/id` for attribute of type `:db.type/keyword` #678

Closed jonasseglare closed 2 months ago

jonasseglare commented 2 months ago

What version of Datahike are you using?

0.6.1659

What version of Java are you using?

openjdk version "20.0.1" 2023-04-18

What operating system are you using?

Ubuntu 22

What database EDN configuration are you using?

{:store {:backend :mem}
   :keep-history? true
   :attribute-refs? true
   :schema-flexibility :write}

Describe the bug

Running the following code against an empty database initialized with the provided config:

        (d/transact conn [{:db/ident :attribute-to-use
                           :db/cardinality :db.cardinality/one
                           :db/valueType :db.type/keyword}])
        (d/transact conn [{:attribute-to-use :the-location}
                          {:attribute-to-use :db/id}])

produces this exception:

 error: clojure.lang.ExceptionInfo: Cannot store nil as a value at [:db/add 41 39 nil] {:error :transact/syntax, :value nil, :context [:db/add 41 39 nil]}

What is the expected behaviour?

That the transaction silently goes through. And that the following query works:

(is (= #{[:the-location]
                 [:db/id]}
               (d/q '[:find ?v
                      :in $ ?a
                      :where
                      [_ :attribute-to-use ?v]]
                    @conn)))

How can the behaviour be reproduced?

By adding the following test code to datahike.test.attribute-refs.differences-test:

(deftest test-store-db-id-as-keyword
  (doseq [cfg (init-cfgs)]
    (testing "Do not resolve enums in keyword DB"
      (let [conn (setup-db cfg)]
        (d/transact conn [{:db/ident :attribute-to-use
                           :db/cardinality :db.cardinality/one
                           :db/valueType :db.type/keyword}])
        (d/transact conn [{:attribute-to-use :the-location}
                          {:attribute-to-use :db/id}])
        (is (= #{[:the-location]
                 [:db/id]}
               (d/q '[:find ?v
                      :in $ ?a
                      :where
                      [_ :attribute-to-use ?v]]
                    @conn)))
        (d/release conn)))))