diff --git a/deps/db-sync/test/logseq/db_sync/normalize_test.cljs b/deps/db-sync/test/logseq/db_sync/normalize_test.cljs new file mode 100644 index 0000000000..c2110c4a2f --- /dev/null +++ b/deps/db-sync/test/logseq/db_sync/normalize_test.cljs @@ -0,0 +1,45 @@ +(ns logseq.db-sync.normalize-test + (:require [cljs.test :refer [deftest is testing]] + [datascript.core :as d] + [logseq.db.common.normalize :as db-normalize] + [logseq.db.test.helper :as db-test])) + +(defn- new-conn [] + (db-test/create-conn)) + +(defn- create-page! + [conn title] + (let [page-uuid (random-uuid)] + (d/transact! conn [{:block/uuid page-uuid + :block/name title + :block/title title}]) + page-uuid)) + +(defn- op-e-a-v + [datom] + (subvec (vec datom) 0 4)) + +(deftest normalize-tx-data-keeps-title-retract-without-replacement-test + (let [conn (new-conn) + page-uuid (create-page! conn "Page") + tx-report (d/transact! conn [[:db/retract [:block/uuid page-uuid] :block/title "Page"]]) + normalized (db-normalize/normalize-tx-data (:db-after tx-report) + (:db-before tx-report) + (:tx-data tx-report)) + tx-data (mapv op-e-a-v normalized)] + (testing "keeps :block/title retract when no replacement title exists in same tx" + (is (= [[:db/retract [:block/uuid page-uuid] :block/title "Page"]] + tx-data))))) + +(deftest normalize-tx-data-drops-title-retract-when-replaced-test + (let [conn (new-conn) + page-uuid (create-page! conn "Page") + tx-report (d/transact! conn [{:block/uuid page-uuid + :block/title "Page 2"}]) + normalized (db-normalize/normalize-tx-data (:db-after tx-report) + (:db-before tx-report) + (:tx-data tx-report)) + tx-data (mapv op-e-a-v normalized)] + (testing "drops old :block/title retract and keeps new add during title update" + (is (some #(= [:db/add [:block/uuid page-uuid] :block/title "Page 2"] %) tx-data)) + (is (not-any? #(= [:db/retract [:block/uuid page-uuid] :block/title "Page"] %) tx-data))))) diff --git a/deps/db-sync/test/logseq/db_sync/test_runner.cljs b/deps/db-sync/test/logseq/db_sync/test_runner.cljs index eb503e1fbb..7654ed1072 100644 --- a/deps/db-sync/test/logseq/db_sync/test_runner.cljs +++ b/deps/db-sync/test/logseq/db_sync/test_runner.cljs @@ -5,6 +5,7 @@ [logseq.db-sync.node-adapter-test] [logseq.db-sync.node-config-test] [logseq.db-sync.node-server-test] + [logseq.db-sync.normalize-test] [logseq.db-sync.platform-test] [logseq.db-sync.worker-auth-test] [logseq.db-sync.worker-handler-assets-test] diff --git a/deps/db/src/logseq/db/common/normalize.cljs b/deps/db/src/logseq/db/common/normalize.cljs index 3b35c2de7a..68b211706f 100644 --- a/deps/db/src/logseq/db/common/normalize.cljs +++ b/deps/db/src/logseq/db/common/normalize.cljs @@ -92,34 +92,46 @@ (defn normalize-tx-data [db-after db-before tx-data] - (->> tx-data - remove-conflict-datoms - (replace-attr-retract-with-retract-entity db-after) - sort-datoms - (keep - (fn [d] - (if (= (count d) 5) - (let [[e a v t added] d - retract? (not added)] - (when-not (and retract? - (contains? #{:block/created-at :block/updated-at :block/title} a)) - (let [e' (if retract? - (eid->lookup db-before e) - (or (eid->lookup db-before e) - (eid->tempid db-after e))) - v' (if (and (integer? v) - (pos? v) - (or (= :db.type/ref (:db/valueType (d/entity db-after a))) - (= :db.type/ref (:db/valueType (d/entity db-before a))))) - (if retract? - (eid->lookup db-before v) - (or (eid->lookup db-before v) - (eid->tempid db-after v))) - v)] - (when (and (some? e') (some? v')) - (if added - [:db/add e' a v' t] - [:db/retract e' a v' t]))))) - d))) - (remove-retract-entity-ref db-after) - distinct)) + (let [title-updated-entities + (->> tx-data + (keep (fn [d] + (when (= (count d) 5) + (let [[e a _v _t added] d] + (when (and added (= :block/title a)) + e))))) + set)] + (->> tx-data + remove-conflict-datoms + (replace-attr-retract-with-retract-entity db-after) + sort-datoms + (keep + (fn [d] + (if (= (count d) 5) + (let [[e a v t added] d + retract? (not added) + drop-retract? + (and retract? + (or (contains? #{:block/created-at :block/updated-at} a) + (and (= :block/title a) + (contains? title-updated-entities e))))] + (when-not drop-retract? + (let [e' (if retract? + (eid->lookup db-before e) + (or (eid->lookup db-before e) + (eid->tempid db-after e))) + v' (if (and (integer? v) + (pos? v) + (or (= :db.type/ref (:db/valueType (d/entity db-after a))) + (= :db.type/ref (:db/valueType (d/entity db-before a))))) + (if retract? + (eid->lookup db-before v) + (or (eid->lookup db-before v) + (eid->tempid db-after v))) + v)] + (when (and (some? e') (some? v')) + (if added + [:db/add e' a v' t] + [:db/retract e' a v' t]))))) + d))) + (remove-retract-entity-ref db-after) + distinct)))