Skip to content

Commit 262f266

Browse files
filipesilvatonsky
authored andcommitted
fix: ensure transitive property for hash value comparisons
Fix #386
1 parent 4a91cf7 commit 262f266

2 files changed

Lines changed: 48 additions & 9 deletions

File tree

src/datascript/db.cljc

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -332,15 +332,28 @@
332332
(if (nil? y) 0
333333
(compare x y))))
334334

335+
(defn class-identical? [x y]
336+
#?(:clj (identical? (class x) (class y))
337+
:cljs (identical? (type x) (type y))))
338+
339+
(defn class-compare [x y]
340+
#?(:clj (compare (.getName (class x)) (.getName (class y)))
341+
:cljs (garray/defaultCompare (type x) (type y))))
342+
335343
(defn value-compare [x y]
336-
(cond
337-
(= x y) 0
338-
#?@(:clj [(instance? Number x) (clojure.lang.Numbers/compare x y)])
339-
#?@(:clj [(instance? Comparable x) (.compareTo ^Comparable x y)]
340-
:cljs [(satisfies? IComparable x) (-compare x y)])
341-
#?@(:cljs [(and (or (string? x) (array? x) (true? x) (false? x))
342-
(identical? (type x) (type y))) (garray/defaultCompare x y)])
343-
:else (- (hash x) (hash y))))
344+
(try
345+
(cond
346+
(= x y) 0
347+
#?@(:clj [(instance? Number x) (clojure.lang.Numbers/compare x y)])
348+
#?@(:clj [(instance? Comparable x) (.compareTo ^Comparable x y)]
349+
:cljs [(satisfies? IComparable x) (-compare x y)])
350+
(not (class-identical? x y)) (class-compare x y)
351+
#?@(:cljs [(or (string? x) (array? x) (true? x) (false? x)) (garray/defaultCompare x y)])
352+
:else (- (hash x) (hash y)))
353+
(catch #?(:clj ClassCastException :cljs js/Error) e
354+
(if (not (class-identical? x y))
355+
(class-compare x y)
356+
(throw e)))))
344357

345358
(defn value-cmp [x y]
346359
(cond

test/datascript/test/transact.cljc

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,4 +439,30 @@
439439
(vec (d/datoms db' :aevt :index 1 {:map 3}))))
440440
(is (= [(db/datom 1 :index {:map 3})]
441441
(vec (d/datoms db' :avet :index {:map 3} 1 )))))
442-
))
442+
))
443+
444+
(deftest test-transitive-type-compare-386
445+
(let [txs [[{:block/uid "2LB4tlJGy"}]
446+
[{:block/uid "2ON453J0Z"}]
447+
[{:block/uid "2KqLLNbPg"}]
448+
[{:block/uid "2L0dcD7yy"}]
449+
[{:block/uid "2KqFNrhTZ"}]
450+
[{:block/uid "2KdQmItUD"}]
451+
[{:block/uid "2O8BcBfIL"}]
452+
[{:block/uid "2L4ZbI7nK"}]
453+
[{:block/uid "2KotiW36Z"}]
454+
[{:block/uid "2O4o-y5J8"}]
455+
[{:block/uid "2KimvuGko"}]
456+
[{:block/uid "dTR20ficj"}]
457+
[{:block/uid "wRmp6bXAx"}]
458+
[{:block/uid "rfL-iQOZm"}]
459+
[{:block/uid "tya6s422-"}]
460+
[{:block/uid 45619}]]
461+
schema {:block/uid {:db/unique :db.unique/identity}}
462+
conn (d/create-conn schema)
463+
_ (doseq [tx txs] (d/transact! conn tx))
464+
db @conn]
465+
(is (empty? (->> (seq db)
466+
(map (fn [[_ a v]] [a v]))
467+
(remove #(d/entity db %)))))))
468+

0 commit comments

Comments
 (0)