Skip to content

Commit

Permalink
fix: ensure transitive property for hash value comparisons
Browse files Browse the repository at this point in the history
Fix #386
  • Loading branch information
filipesilva authored and tonsky committed Mar 6, 2021
1 parent 4a91cf7 commit 262f266
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 9 deletions.
29 changes: 21 additions & 8 deletions src/datascript/db.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -332,15 +332,28 @@
(if (nil? y) 0
(compare x y))))

(defn class-identical? [x y]
#?(:clj (identical? (class x) (class y))
:cljs (identical? (type x) (type y))))

(defn class-compare [x y]
#?(:clj (compare (.getName (class x)) (.getName (class y)))
:cljs (garray/defaultCompare (type x) (type y))))

(defn value-compare [x y]
(cond
(= x y) 0
#?@(:clj [(instance? Number x) (clojure.lang.Numbers/compare x y)])
#?@(:clj [(instance? Comparable x) (.compareTo ^Comparable x y)]
:cljs [(satisfies? IComparable x) (-compare x y)])
#?@(:cljs [(and (or (string? x) (array? x) (true? x) (false? x))
(identical? (type x) (type y))) (garray/defaultCompare x y)])
:else (- (hash x) (hash y))))
(try
(cond
(= x y) 0
#?@(:clj [(instance? Number x) (clojure.lang.Numbers/compare x y)])
#?@(:clj [(instance? Comparable x) (.compareTo ^Comparable x y)]
:cljs [(satisfies? IComparable x) (-compare x y)])
(not (class-identical? x y)) (class-compare x y)
#?@(:cljs [(or (string? x) (array? x) (true? x) (false? x)) (garray/defaultCompare x y)])
:else (- (hash x) (hash y)))
(catch #?(:clj ClassCastException :cljs js/Error) e
(if (not (class-identical? x y))
(class-compare x y)
(throw e)))))

(defn value-cmp [x y]
(cond
Expand Down
28 changes: 27 additions & 1 deletion test/datascript/test/transact.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -439,4 +439,30 @@
(vec (d/datoms db' :aevt :index 1 {:map 3}))))
(is (= [(db/datom 1 :index {:map 3})]
(vec (d/datoms db' :avet :index {:map 3} 1 )))))
))
))

(deftest test-transitive-type-compare-386
(let [txs [[{:block/uid "2LB4tlJGy"}]
[{:block/uid "2ON453J0Z"}]
[{:block/uid "2KqLLNbPg"}]
[{:block/uid "2L0dcD7yy"}]
[{:block/uid "2KqFNrhTZ"}]
[{:block/uid "2KdQmItUD"}]
[{:block/uid "2O8BcBfIL"}]
[{:block/uid "2L4ZbI7nK"}]
[{:block/uid "2KotiW36Z"}]
[{:block/uid "2O4o-y5J8"}]
[{:block/uid "2KimvuGko"}]
[{:block/uid "dTR20ficj"}]
[{:block/uid "wRmp6bXAx"}]
[{:block/uid "rfL-iQOZm"}]
[{:block/uid "tya6s422-"}]
[{:block/uid 45619}]]
schema {:block/uid {:db/unique :db.unique/identity}}
conn (d/create-conn schema)
_ (doseq [tx txs] (d/transact! conn tx))
db @conn]
(is (empty? (->> (seq db)
(map (fn [[_ a v]] [a v]))
(remove #(d/entity db %)))))))

0 comments on commit 262f266

Please sign in to comment.