tonsky / datascript

Immutable database and Datalog query engine for Clojure, ClojureScript and JS
Eclipse Public License 1.0
5.45k stars 304 forks source link

Regression in 1.6.4: Can’t sum relations with different attrs #468

Closed mainej closed 4 months ago

mainej commented 4 months ago

I'm upgrading from 1.6.3 to 1.6.4 and started getting a new exception with one of my queries Can’t sum relations with different attrs.

I've created a reproduction. It's as small as I can make it, though it's still somewhat complicated.

(let [db (-> (d/empty-db {:parent {:db/valueType :db.type/ref}})
             (d/with [{:db/id "alice"
                       :name "alice"}
                      {:db/id "bob"
                       :name "bob"}
                      {:db/id "clara"
                       :name "clara"}
                      [:db/add "alice" :parent "bob"]
                      [:db/add "bob" :parent "clara"]])
             :db-after)]
  (for [name ["alice" "bob" "clara"]]
    [name
     (try
       (d/q '[:find ?x ?y
              :in $ ?name
              :where
              [?x :name ?name]
              (or-join
               [?x ?y]
               (and [?x :parent ?z]
                    [?z :parent ?y])
               [?y :parent ?x])]
            db
            name)
       (catch Exception e
         e))]))

In 1.6.3 this produces

(["alice" #{[1 3]}] 
 ["bob" #{[2 1]}]
 ["clara" #{[3 2]}])

In 1.6.4 it produces

(["alice" #{[1 3]}] 
 ["bob" #{[2 1]}] 
 ["clara" #error {
 :cause "Can’t sum relations with different attrs: {?x \"e\"} and {?x 0, ?y 1}"
 :data {:error :query/where}
 :via
 [{:type clojure.lang.ExceptionInfo
   :message "Can’t sum relations with different attrs: {?x \"e\"} and {?x 0, ?y 1}"
   :data {:error :query/where}
   :at [datascript.query$sum_rel invokeStatic "query.cljc" 160]}]
 :trace
 [[datascript.query$sum_rel invokeStatic "query.cljc" 160]
  [datascript.query$sum_rel invoke "query.cljc" 147]
  [clojure.core.protocols$fn__8285 invokeStatic "protocols.clj" 167]
  [clojure.core.protocols$fn__8285 invoke "protocols.clj" 123]
  [clojure.core.protocols$fn__8239$G__8234__8248 invoke "protocols.clj" 693]
  [clojure.core.protocols$seq_reduce invokeStatic "protocols.clj" 27]
  [clojure.core.protocols$fn__8272 invokeStatic "protocols.clj" 74]
  [clojure.core.protocols$fn__8272 invoke "protocols.clj" 74]
  [clojure.core.protocols$fn__8213$G__8208__8226 invoke "protocols.clj" 693]
  [clojure.core$reduce invokeStatic "core.clj" 6951]
  [clojure.core$reduce invoke "core.clj" 6937]
  [datascript.query$_resolve_clause invokeStatic "query.cljc" 774]
  [datascript.query$_resolve_clause invoke "query.cljc" 733]
  [datascript.query$_resolve_clause invokeStatic "query.cljc" 735]
  [datascript.query$_resolve_clause invoke "query.cljc" 733]
  [datascript.query$resolve_clause invokeStatic "query.cljc" 828]
  [datascript.query$resolve_clause invoke "query.cljc" 820]
  [clojure.lang.PersistentVector reduce "PersistentVector.java" 418]
  [clojure.core$reduce invokeStatic "core.clj" 6954]
  [clojure.core$reduce invoke "core.clj" 6937]
  [datascript.query$_q invokeStatic "query.cljc" 832]
  [datascript.query$_q invoke "query.cljc" 830]
  [datascript.query$q invokeStatic "query.cljc" 997]
  [datascript.query$q doInvoke "query.cljc" 982]
  [clojure.lang.RestFn invoke "RestFn.java" 442]
  SNIP]}])

From playing with variations of the query, the error seems to come from the second clause of the and inside the or-join. I don't know the internals of datascript, but my guess is that something like this has started happening:

tonsky commented 4 months ago

Thanks! It’s tricky even to reproduce :) Hopefully fixed in 1.6.5