Skip to content

Commit

Permalink
Stable sorting of sequences of various types #470
Browse files Browse the repository at this point in the history
  • Loading branch information
tonsky committed May 23, 2024
1 parent a527437 commit d67931b
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 3 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# WIP

- Stable sorting of sequences of various types #470

# 1.6.5 - May 3, 2024

- Regression: fixed some OR queries broken in 1.6.4 #468 #469
Expand Down
39 changes: 37 additions & 2 deletions src/datascript/db.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -438,11 +438,46 @@
#?(:clj (. clojure.lang.Util (hasheq x))
:cljs (hash x)))

(defn value-compare
^long [x y]
(declare+ ^number value-compare [x y])

(defn- seq-compare [xs ys]
(let [cx (count xs)
cy (count ys)]
(cond
(< cx cy)
-1

(> cx cy)
1

:else
(loop [xs xs
ys ys]
(if (empty? xs)
0
(let [x (first xs)
y (first ys)]
(cond
(and (nil? x) (nil? y))
(recur (next xs) (next ys))

(nil? x)
-1

(nil? y)
1

:else
(let [v (value-compare x y)]
(if (= v 0)
(recur (next xs) (next ys))
v)))))))))

(defn+ ^number value-compare [x y]
(try
(cond
(= x y) 0
(and (sequential? x) (sequential? y)) (seq-compare x y)
#?@(: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)])
Expand Down
20 changes: 19 additions & 1 deletion test/datascript/test/index.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,25 @@
(d/datoms db :avet :name "Ivan")))

(is (thrown-msg? "Attribute :name should be marked as :db/index true"
(d/datoms db :avet :name "Ivan" 1))))))
(d/datoms db :avet :name "Ivan" 1))))

(testing "Sequence compare issue-470"
(let [db (-> (d/empty-db {:path {:db/index true}})
(d/db-with [{:db/id 1 :path [1 2]}
{:db/id 2 :path [1 2 3]}]))]
(are [value result] (= result (mapv :e (d/datoms db :avet :path value)))
[1] []
[1 1] []
[1 2] [1]
(list 1 2) [1]
(butlast [1 2 3]) [1]
[1 3] []
[1 2 2] []
[1 2 3] [2]
(list 1 2 3) [2]
(butlast [1 2 3 4]) [2]
[1 2 4] []
[1 2 3 4] [])))))

(deftest test-datom
(let [dvec #(when % (vector (:e %) (:a %) (:v %)))
Expand Down

0 comments on commit d67931b

Please sign in to comment.