Browse Source

Merge branch 'feat/db' into enhance/reference-view

Tienson Qin 8 months ago
parent
commit
bd779e3007

+ 8 - 10
deps/common/src/logseq/common/uuid.cljs

@@ -19,10 +19,9 @@ the remaining chars for data of this type"
   (let [s-length (count s)]
     (apply str s (repeat (- length s-length) "0"))))
 
-(defn gen-block-uuid
+(defn- gen-block-uuid
   "prefix-<hash-of-db-ident>-<padding-with-0>"
   [k prefix]
-  {:pre [(keyword? k)]}
   (let [hash-num (str (Math/abs (hash k)))
         part1 (fill-with-0 (subs hash-num 0 4) 4)
         part2 (fill-with-0 (subs hash-num 4 8) 4)
@@ -36,18 +35,17 @@ the remaining chars for data of this type"
   {:pre [(keyword? db-ident)]}
   (gen-block-uuid db-ident "00000002"))
 
-;; 00000001 journal
-;; 00000002 db ident
-;; 00000003 new blocks created by migration
-
 (defn gen-uuid
   "supported type:
-  - :journal-page-uuid
-  - :db-ident-block-uuid
-  - :migrate-new-block-uuid"
+  - :journal-page-uuid, 00000001
+  - :db-ident-block-uuid, 00000002
+  - :migrate-new-block-uuid, 00000003
+  - :builtin-block-uuid, 00000004"
   ([] (d/squuid))
   ([type' v]
+   (assert (some? v))
    (case type'
      :journal-page-uuid (gen-journal-page-uuid v)
      :db-ident-block-uuid (gen-db-ident-block-uuid v)
-     :migrate-new-block-uuid (gen-block-uuid v "00000003"))))
+     :migrate-new-block-uuid (gen-block-uuid v "00000003")
+     :builtin-block-uuid (gen-block-uuid v "00000004"))))

+ 23 - 9
deps/db/src/logseq/db/frontend/property/build.cljs

@@ -1,7 +1,7 @@
 (ns logseq.db.frontend.property.build
   "Builds core property concepts"
-  (:require [datascript.core :as d]
-            [logseq.common.util :as common-util]
+  (:require [logseq.common.util :as common-util]
+            [logseq.common.uuid :as common-uuid]
             [logseq.db.common.order :as db-order]
             [logseq.db.frontend.property :as db-property]
             [logseq.db.frontend.property.type :as db-property-type]
@@ -68,10 +68,10 @@
 (defn- build-property-value-block
   "Builds a property value entity given a block map/entity, a property entity or
   ident and its property value"
-  [block property value]
+  [block property value & {:keys [block-uuid]}]
   (let [block-id (or (:db/id block) (:db/ident block))]
     (-> (merge
-         {:block/uuid (d/squuid)
+         {:block/uuid (or block-uuid (common-uuid/gen-uuid))
           :block/page (if (:block/page block)
                         (:db/id (:block/page block))
                         ;; page block
@@ -91,18 +91,32 @@
   transacted, given a block and a properties map with raw property values. The
   properties map can have keys that are db-idents or they can be maps. If a map,
   it should have :original-property-id and :db/ident keys.  See
-  ->property-value-tx-m for such an example"
-  [block properties]
+  ->property-value-tx-m for such an example
+
+  :pure? - ensure this fn is a pure function"
+  [block properties & {:keys [pure?]}]
   ;; Build :db/id out of uuid if block doesn't have one for tx purposes
   (let [block' (if (:db/id block) block (assoc block :db/id [:block/uuid (:block/uuid block)]))]
     (->> properties
          (map (fn [[k v]]
-                (let [property-map (if (map? k) k {:db/ident k})]
+                (let [property-map (if (map? k) k {:db/ident k})
+                      gen-uuid-value-prefix (when pure?
+                                              (or (:db/ident block) (:block/uuid block)))]
                   (assert (:db/ident property-map) "Key in map must have a :db/ident")
+                  (when pure? (assert (some? gen-uuid-value-prefix) block))
                   [(or (:original-property-id property-map) (:db/ident property-map))
                    (if (set? v)
-                     (set (map #(build-property-value-block block' property-map %) v))
-                     (build-property-value-block block' property-map v))])))
+                     (set (map #(build-property-value-block
+                                 block' property-map %
+                                 (when pure?
+                                   {:block-uuid
+                                    (common-uuid/gen-uuid :builtin-block-uuid (str gen-uuid-value-prefix "-" %))}))
+                               v))
+                     (build-property-value-block block' property-map v
+                                                 (when pure?
+                                                   {:block-uuid
+                                                    (common-uuid/gen-uuid
+                                                     :builtin-block-uuid (str gen-uuid-value-prefix "-" v))})))])))
          (into {}))))
 
 (defn build-properties-with-ref-values

+ 22 - 20
deps/db/src/logseq/db/sqlite/create_graph.cljs

@@ -1,10 +1,10 @@
 (ns logseq.db.sqlite.create-graph
   "Helper fns for creating a DB graph"
   (:require [clojure.string :as string]
-            [datascript.core :as d]
             [logseq.common.config :as common-config]
             [logseq.common.util :as common-util]
             [logseq.common.uuid :as common-uuid]
+            [logseq.db.common.order :as db-order]
             [logseq.db.frontend.class :as db-class]
             [logseq.db.frontend.entity-util :as entity-util]
             [logseq.db.frontend.malli-schema :as db-malli-schema]
@@ -31,20 +31,22 @@
   "Given a new block and its properties, creates a map of properties which have values of property value tx.
    This map is used for both creating the new property values and then adding them to a block"
   [new-block properties]
-  (->> properties
-       (keep (fn [[k v]]
-               (when-let [built-in-type (get-in db-property/built-in-properties [k :schema :type])]
-                 (if (and (db-property-type/value-ref-property-types built-in-type)
-                          ;; closed values are referenced by their :db/ident so no need to create values
-                          (not (get-in db-property/built-in-properties [k :closed-values])))
-                   (let [property-map {:db/ident k
-                                       :logseq.property/type built-in-type}]
-                     [property-map v])
-                   (when-let [built-in-type' (get (:build/properties-ref-types new-block) built-in-type)]
-                     (let [property-map {:db/ident k
-                                         :logseq.property/type built-in-type'}]
-                       [property-map v]))))))
-       (db-property-build/build-property-values-tx-m new-block)))
+  (db-property-build/build-property-values-tx-m
+   new-block
+   (->> properties
+        (keep (fn [[k v]]
+                (when-let [built-in-type (get-in db-property/built-in-properties [k :schema :type])]
+                  (if (and (db-property-type/value-ref-property-types built-in-type)
+                           ;; closed values are referenced by their :db/ident so no need to create values
+                           (not (get-in db-property/built-in-properties [k :closed-values])))
+                    (let [property-map {:db/ident k
+                                        :logseq.property/type built-in-type}]
+                      [property-map v])
+                    (when-let [built-in-type' (get (:build/properties-ref-types new-block) built-in-type)]
+                      (let [property-map {:db/ident k
+                                          :logseq.property/type built-in-type'}]
+                        [property-map v])))))))
+   :pure? true))
 
 (defn build-properties
   "Given a properties map in the format of db-property/built-in-properties, builds their properties tx"
@@ -169,7 +171,7 @@
 (defn build-initial-views
   "Builds initial blocks used for storing views. Used by db and file graphs"
   []
-  (let [page-id (common-uuid/gen-uuid)]
+  (let [page-id (common-uuid/gen-uuid :builtin-block-uuid common-config/views-page-name)]
     [(sqlite-util/block-with-timestamps
       {:block/uuid page-id
        :block/name common-config/views-page-name
@@ -181,7 +183,7 @@
 (defn- build-favorites-page
   []
   [(sqlite-util/block-with-timestamps
-    {:block/uuid (common-uuid/gen-uuid)
+    {:block/uuid (common-uuid/gen-uuid :builtin-block-uuid common-config/favorites-page-name)
      :block/name common-config/favorites-page-name
      :block/title common-config/favorites-page-name
      :block/tags [:logseq.class/Page]
@@ -202,17 +204,17 @@
                        {:db/ident :logseq.property/empty-placeholder}]
                        import-type
                        (into (sqlite-util/import-tx import-type)))
-        initial-files [{:block/uuid (d/squuid)
+        initial-files [{:block/uuid (common-uuid/gen-uuid :builtin-block-uuid "logseq/config.edn")
                         :file/path (str "logseq/" "config.edn")
                         :file/content config-content
                         :file/created-at (js/Date.)
                         :file/last-modified-at (js/Date.)}
-                       {:block/uuid (d/squuid)
+                       {:block/uuid (common-uuid/gen-uuid :builtin-block-uuid "logseq/custom.css")
                         :file/path (str "logseq/" "custom.css")
                         :file/content ""
                         :file/created-at (js/Date.)
                         :file/last-modified-at (js/Date.)}
-                       {:block/uuid (d/squuid)
+                       {:block/uuid (common-uuid/gen-uuid :builtin-block-uuid "logseq/custom.js")
                         :file/path (str "logseq/" "custom.js")
                         :file/content ""
                         :file/created-at (js/Date.)

+ 2 - 2
deps/db/src/logseq/db/sqlite/util.cljs

@@ -3,7 +3,7 @@
   (:require [cljs-bean.transit]
             [clojure.string :as string]
             [cognitect.transit :as transit]
-            [datascript.core :as d]
+            [datascript.core]
             [datascript.impl.entity :as de]
             [datascript.transit :as dt]
             [logseq.common.util :as common-util]
@@ -121,7 +121,7 @@
   (block-with-timestamps
    {:block/name (common-util/page-name-sanity-lc page-name)
     :block/title page-name
-    :block/uuid (d/squuid)
+    :block/uuid (common-uuid/gen-uuid :builtin-block-uuid page-name)
     :block/tags #{:logseq.class/Page}}))
 
 (defn kv

+ 19 - 0
deps/db/test/logseq/db/sqlite/create_graph_test.cljs

@@ -1,5 +1,6 @@
 (ns logseq.db.sqlite.create-graph-test
   (:require [cljs.test :refer [deftest is testing]]
+            [clojure.data :as data]
             [clojure.set :as set]
             [clojure.string :as string]
             [datascript.core :as d]
@@ -150,3 +151,21 @@
 
       (is (empty? (map :entity (:errors (db-validate/validate-db! @conn))))
           "Graph with different :url blocks has no validation errors"))))
+
+(deftest build-db-initial-data-test
+  (testing "idempotent initial-data"
+    (letfn [(remove-ignored-attrs&entities [init-data]
+              (let [[before after] (split-with #(not= :logseq.kv/graph-created-at (:db/ident %)) init-data)
+                    init-data* (concat before (rest after))]
+                (map (fn [ent] (dissoc ent
+                                       :block/created-at :block/updated-at
+                                       :file/last-modified-at :file/created-at
+                                       :block/order ;; TODO: block/order should be same as well
+                                       ))
+                     init-data*)))]
+      (let [[first-only second-only common]
+            (data/diff (remove-ignored-attrs&entities (sqlite-create-graph/build-db-initial-data ""))
+                       (remove-ignored-attrs&entities (sqlite-create-graph/build-db-initial-data "")))]
+        (is (and (every? nil? first-only)
+                 (every? nil? second-only))
+            (pr-str [first-only second-only common]))))))