Environment
- com.datomic/client-cloud "1.0.117"
- com.datomic/dev-local 1.0.238
History
(def client (d/client {:server-type :dev-local
:storage-dir :mem
:system "test"}))
=> #'user/client
(d/create-database client {:db-name "a"})
=> true
(def conn (d/connect client {:db-name "a"}))
=> #'user/conn
(d/q '[:find (pull ?e [:db/doc]) (pull ?e [:db/ident])
:where
[?e :db/ident :db/cardinality]]
(d/db conn))
Execution error (ArrayIndexOutOfBoundsException) at datomic.core.datalog/fn$project (datalog.clj:560).
Index 1 out of bounds for length 1
If you bind the same eid to a new var name, the exception will not be thrown.
(d/q '[:find (pull ?e [:db/doc]) (pull ?e2 [:db/ident])
:where
[?e :db/ident :db/cardinality]
[(identity ?e) ?e2]]
(d/db conn))
=>
[[#:db{:doc "Property of an attribute. Two possible values: :db.cardinality/one for single-valued attributes, and :db.cardinality/many for many-valued attributes. Defaults to :db.cardinality/one."}
#:db{:ident :db/cardinality}]]
Expectation
Pulling the same entity in multiple locations in :find
will pull the relevant data and not thrown an ArrayIndexOutOfBoundsException
.
Actual
Pulling the same entity in multiple locations in :find
throws an ArrayIndexOutOfBoundsException
.
Evidence
Full stacktrace:
#error{:cause "Index 1 out of bounds for length 1",
:via [{:type clojure.lang.ExceptionInfo,
:message "processing clause: [?e :db/ident :db/cardinality], message: java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1",
:data #:cognitect.anomalies{:category :cognitect.anomalies/incorrect,
:message "processing clause: [?e :db/ident :db/cardinality], message: java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1"},
:at [datomic.core.datalog$throw_query_ex_BANG_ invokeStatic "datalog.clj" 50]}
{:type java.lang.ArrayIndexOutOfBoundsException,
:message "Index 1 out of bounds for length 1",
:at [clojure.lang.RT aset "RT.java" 2384]}],
:trace [[clojure.lang.RT aset "RT.java" 2384]
[datomic.core.datalog$fn__22911$project__22994 invoke "datalog.clj" 560]
[datomic.core.datalog$fn__22911$join__23012 invoke "datalog.clj" 659]
[datomic.core.datalog$fn__22911$fn__23015 invoke "datalog.clj" 666]
[datomic.core.common$pooled_mapv$fn__22667$fn__22668 invoke "common.clj" 490]
[clojure.lang.AFn applyToHelper "AFn.java" 152]
[clojure.lang.AFn applyTo "AFn.java" 144]
[clojure.core$apply invokeStatic "core.clj" 667]
[clojure.core$with_bindings_STAR_ invokeStatic "core.clj" 1977]
[clojure.core$with_bindings_STAR_ doInvoke "core.clj" 1977]
[clojure.lang.RestFn invoke "RestFn.java" 425]
[clojure.lang.AFn applyToHelper "AFn.java" 156]
[clojure.lang.RestFn applyTo "RestFn.java" 132]
[clojure.core$apply invokeStatic "core.clj" 671]
[clojure.core$bound_fn_STAR_$fn__5767 doInvoke "core.clj" 2007]
[clojure.lang.RestFn invoke "RestFn.java" 397]
[clojure.lang.AFn call "AFn.java" 18]
[java.util.concurrent.FutureTask run "FutureTask.java" 264]
[java.util.concurrent.ThreadPoolExecutor runWorker "ThreadPoolExecutor.java" 1128]
[java.util.concurrent.ThreadPoolExecutor$Worker run "ThreadPoolExecutor.java" 628]
[java.lang.Thread run "Thread.java" 829]]}
Impact
Programmatically built queries that expect two positions in :find
must apply a workaround to avoid the exception.