-
-
Notifications
You must be signed in to change notification settings - Fork 101
Description
What version of Datahike are you using?
0.6.1607
What version of Java are you using?
openjdk 24.0.2 2025-07-15
What operating system are you using?
Ubuntu
What database EDN configuration are you using?
{:store {:backend :mem :id "cfg1"} :attribute-refs? true}
Describe the bug
The ordering in which I declare the kvs for the map representing a :db/tupleAttrs schema matters. If the :db/ident comes first all is good, if it comes last a java.lang.ClassCastException is thrown with the message:
"class java.lang.Long cannot be cast to class clojure.lang.IFn (java.lang.Long is in module java.base of loader 'bootstrap'; clojure.lang.IFn is in unnamed module of loader 'app')"
In other words this will transact fine:
{:db/ident :reg/semester+course+student
:db/valueType :db.type/tuple
:db/tupleAttrs [:reg/course :reg/semester :reg/student]
:db/cardinality :db.cardinality/one}])While this will throw:
{ :db/valueType :db.type/tuple
:db/tupleAttrs [:reg/course :reg/semester :reg/student]
:db/cardinality :db.cardinality/one
:db/ident :reg/semester+course+student}])What is the expected behaviour?
This problem may come from the ordering of the key value pairs in the underlying Clojure ArrayMap. This is the only thing I can think of that might influence the issue. The expected behavior would be for the transaction to go through regardless of that ordering.
How can the behaviour be reproduced?
Here is the code snippet I use to reproduce the problem in a repl:
(ns repro
(:require
[datahike.api :as d]))
;; -----------------------------------------------------------------------------
;; Example 1
;; -----------------------------------------------------------------------------
(def cfg1 {:store {:backend :mem :id "cfg1"} :attribute-refs? true})
(d/create-database cfg1)
(def conn1 (d/connect cfg1))
;; here :db/ident is comes first
(def schema1
[{:db/ident :reg/semester+course+student
:db/valueType :db.type/tuple
:db/tupleAttrs [:reg/course :reg/semester :reg/student]
:db/cardinality :db.cardinality/one}])
(comment
;; The schema is accepted
(d/transact conn1 schema1))
;; -----------------------------------------------------------------------------
;; Example 2
;; -----------------------------------------------------------------------------
(def cfg2 {:store {:backend :mem :id "cfg2"}
:attribute-refs? true})
(d/create-database cfg2)
(def conn2 (d/connect cfg2))
;; here :db/ident comes last
(def schema2
[{:db/valueType :db.type/tuple
:db/tupleAttrs [:reg/course :reg/semester :reg/student]
:db/cardinality :db.cardinality/one
:db/ident :reg/semester+course+student}])
(comment
;; An exception is thrown
(d/transact conn2 schema2))