Environment
- com.datomic/client-cloud "1.0.119"
- com.datomic/dev-local 1.0.242
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 ?e
:where
[?e :db/ident :db/cardinality]
:with ?e]
(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 remove the duplicate binding from :with
, the exception will not be thrown.
(d/q '[:find ?e
:where [?e :db/ident :db/cardinality]]
(d/db conn))
=> [[41]]
Expectation
A duplicate var in :find
and :with
returns the same result as no duplicate.
Actual
A duplicate var in :find
and :with
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" 2381]}],
:trace [[clojure.lang.RT aset "RT.java" 2381]
[datomic.core.datalog$fn__24749$project__24832 invoke "datalog.clj" 560]
[datomic.core.datalog$fn__24749$join__24850 invoke "datalog.clj" 659]
[datomic.core.datalog$fn__24749$fn__24853 invoke "datalog.clj" 666]
[datomic.core.common$pooled_mapv$fn__24505$fn__24506 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" 1990]
[clojure.core$with_bindings_STAR_ doInvoke "core.clj" 1990]
[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__5818 doInvoke "core.clj" 2020]
[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 always add a :with
clause need to detect and remove duplicates prior to issuing the query. This results in extra code and unknown edge cases surfacing.