fix: db import of properties that conflict with new built-in property names

Fixes LOG-3039. This was noticed because new description built-in
conflicted with file graphs that had the same name. This fixes the issue
for :description but also any of the other new db built-in property
names
pull/11458/head^2
Gabriel Horner 2024-08-05 15:13:10 -04:00
parent 1f8788f5ad
commit e9d1ec1cef
1 changed files with 37 additions and 13 deletions

View File

@ -294,12 +294,19 @@
[(:name v) k]))
(into {})))
(def built-in-property-names
"Set of all built-in property names as keywords. Using in-memory property
names because these are legacy names already in a user's file graph"
;; Should this move to logseq.db.frontend.property to be better maintained?
(def db-only-built-in-property-names
"Built-in property names that are are only used by DB graphs"
#{:description :page-tags :hide-properties? :created-from-property
:built-in? :includes :excludes :status :priority :deadline :sorting
:hidden-columns :ordered-columns :view-for :remote-metadata})
(def file-built-in-property-names
"Built-in property names for file graphs that are imported. Expressed as set of keywords"
(-> built-in-property-name-to-idents keys set
;; :filters is not in built-in-properties because it maps to 2 new properties
(conj :filters)))
(conj :filters)
(set/difference db-only-built-in-property-names)))
(defn- update-built-in-property-values
[props {:keys [ignored-properties all-idents]} {:block/keys [title name]} options]
@ -433,7 +440,7 @@
{:keys [import-state] :as options}]
(let [{:keys [all-idents property-schemas]} import-state
get-ident' #(get-ident @all-idents %)
user-properties (apply dissoc props built-in-property-names)]
user-properties (apply dissoc props file-built-in-property-names)]
(when (seq user-properties)
(swap! (:block-properties-text-values import-state)
assoc
@ -444,7 +451,7 @@
(if (contains? props :template)
{}
(let [props' (-> (update-built-in-property-values
(select-keys props built-in-property-names)
(select-keys props file-built-in-property-names)
(select-keys import-state [:ignored-properties :all-idents])
(select-keys block [:block/name :block/title])
(select-keys options [:property-classes]))
@ -479,7 +486,7 @@
class-related-properties)]
(->> (apply dissoc properties dissoced-props)
(keep (fn [[prop val]]
(if (not (contains? built-in-property-names prop))
(if (not (contains? file-built-in-property-names prop))
;; only update user properties
(if (string? val)
;; Ignore blank values as they were usually generated by templates
@ -508,7 +515,7 @@
properties-to-infer (if (:template properties')
;; Ignore template properties as they don't consistently have representative property values
{}
(apply dissoc properties' built-in-property-names))
(apply dissoc properties' file-built-in-property-names))
property-changes
(->> properties-to-infer
(keep (fn [[prop val]]
@ -676,9 +683,22 @@
(not (:block/file %))))
;; remove file path relative
(map #(dissoc % :block/file)))
existing-pages (keep #(ldb/get-page @conn (:block/name %)) all-pages)
existing-pages (keep #(first
;; don't fetch built-in as that would give the wrong entity if a user used
;; a db-only built-in property name e.g. description
(d/q '[:find [(pull ?b [*]) ...]
:in $ ?name
:where [?b :block/name ?name] [(missing? $ ?b :logseq.property/built-in?)]]
@conn
(:block/name %)))
all-pages)
existing-page-names-to-uuids (into {} (map (juxt :block/name :block/uuid) existing-pages))
new-pages (remove #(contains? existing-page-names-to-uuids (:block/name %)) all-pages)
new-pages (->> all-pages
(remove #(contains? existing-page-names-to-uuids (:block/name %)))
;; fix extract incorrectly assigning user properties built-in property uuids
(map #(if (contains? db-only-built-in-property-names (keyword (:block/name %)))
(assoc % :block/uuid (d/squuid))
%)))
page-names-to-uuids (merge existing-page-names-to-uuids
(into {} (map (juxt :block/name :block/uuid) new-pages)))
all-pages-m (mapv #(handle-page-properties % @conn page-names-to-uuids all-pages options)
@ -701,7 +721,11 @@
(update-page-alias page-names-to-uuids)
(:block/tags m)
(update-page-tags @conn tag-classes page-names-to-uuids (:all-idents import-state)))))
(build-new-page m @conn tag-classes page-names-to-uuids (:all-idents import-state))))
(let [m' (if (contains? db-only-built-in-property-names (keyword (:block/name m)))
;; Use fixed uuid from above
(assoc m :block/uuid (get page-names-to-uuids (:block/name m)))
m)]
(build-new-page m' @conn tag-classes page-names-to-uuids (:all-idents import-state)))))
(map :block all-pages-m))]
{:pages-tx pages-tx
:page-properties-tx (mapcat :properties-tx all-pages-m)
@ -791,10 +815,10 @@
:tag-classes (set (map string/lower-case (:tag-classes user-options)))
:property-classes (set/difference
(set (map (comp keyword string/lower-case) (:property-classes user-options)))
built-in-property-names)
file-built-in-property-names)
:property-parent-classes (set/difference
(set (map (comp keyword string/lower-case) (:property-parent-classes user-options)))
built-in-property-names)}))
file-built-in-property-names)}))
(defn- split-pages-and-properties-tx
"Separates new pages from new properties tx in preparation for properties to