|
9 | 9 | [logseq.common.config :as common-config] |
10 | 10 | [logseq.common.util :as common-util] |
11 | 11 | [logseq.db :as ldb] |
12 | | - [logseq.db.common.order :as db-order] |
13 | 12 | [logseq.db.frontend.class :as db-class] |
14 | | - [logseq.db.frontend.db-ident :as db-ident] |
15 | 13 | [logseq.db.frontend.property :as db-property] |
16 | 14 | [logseq.db.frontend.schema :as db-schema] |
17 | 15 | [logseq.db.sqlite.create-graph :as sqlite-create-graph] |
|
20 | 18 | ;; Frontend migrations |
21 | 19 | ;; =================== |
22 | 20 |
|
23 | | -(defn- rename-properties-aux |
| 21 | +(defn- rename-properties-fix |
24 | 22 | [db props-to-rename] |
25 | | - (let [property-tx (map |
| 23 | + (let [;; update property title/name |
| 24 | + ;; don't update :db/ident since it's addressed by `:rename-db-idents` |
| 25 | + property-tx (map |
26 | 26 | (fn [[old new]] |
27 | | - (let [e-new (d/entity db new) |
28 | | - e-old (d/entity db old)] |
29 | | - (if e-new |
30 | | - (when e-old |
31 | | - [:db/retractEntity (:db/id e-old)]) |
32 | | - (merge {:db/id (:db/id (d/entity db old)) |
33 | | - :db/ident new} |
34 | | - (when-let [new-title (get-in db-property/built-in-properties [new :title])] |
35 | | - {:block/title new-title |
36 | | - :block/name (common-util/page-name-sanity-lc new-title)}))))) |
| 27 | + (merge {:db/id (:db/id (d/entity db old))} |
| 28 | + (when-let [new-title (get-in db-property/built-in-properties [new :title])] |
| 29 | + {:block/title new-title |
| 30 | + :block/name (common-util/page-name-sanity-lc new-title)}))) |
37 | 31 | props-to-rename) |
38 | 32 | titles-tx (->> (d/datoms db :avet :block/title) |
39 | 33 | (keep (fn [d] |
|
118 | 112 | ordered-columns-tx |
119 | 113 | filters-tx))) |
120 | 114 |
|
121 | | -(defn rename-properties |
122 | | - [props-to-rename & {:keys [replace-fn]}] |
123 | | - (fn [db] |
124 | | - (when (ldb/db-based-graph? db) |
125 | | - (let [props-tx (rename-properties-aux db props-to-rename) |
126 | | - fix-tx (mapcat (fn [[old new]] |
127 | | - ;; can't use datoms b/c user properties aren't indexed |
128 | | - (->> (d/q '[:find ?b ?prop-v :in $ ?prop :where [?b ?prop ?prop-v]] db old) |
129 | | - (mapcat (fn [[id prop-value]] |
130 | | - (if (fn? replace-fn) |
131 | | - (replace-fn id prop-value) |
132 | | - [[:db/retract id old] |
133 | | - [:db/add id new prop-value]]))))) |
134 | | - props-to-rename)] |
135 | | - (concat props-tx fix-tx))))) |
| 115 | +(defn- rename-properties |
| 116 | + [props-to-rename {:keys [fix]}] |
| 117 | + {:rename-db-idents (mapv |
| 118 | + (fn [[old-ident new-ident]] |
| 119 | + {:db-ident-or-block-uuid old-ident |
| 120 | + :new-db-ident new-ident}) |
| 121 | + props-to-rename) |
| 122 | + :fix (fn [db] |
| 123 | + (let [common-fix (rename-properties-fix db |
| 124 | + {:logseq.property.asset/external-src |
| 125 | + :logseq.property.asset/external-url}) |
| 126 | + additional-fix (when (fn? fix) |
| 127 | + (fix db))] |
| 128 | + (concat common-fix additional-fix)))}) |
136 | 129 |
|
137 | 130 | (comment |
138 | 131 | (defn- rename-classes |
|
147 | 140 | :block/name (common-util/page-name-sanity-lc new-title)}))) |
148 | 141 | classes-to-rename))))) |
149 | 142 |
|
150 | | -(defn fix-rename-parent-to-extends |
151 | | - [db] |
152 | | - (let [parent-entity (d/entity db :logseq.property/parent)] |
153 | | - (when parent-entity |
154 | | - (let [old-p :logseq.property/parent |
155 | | - new-p :logseq.property.class/extends |
156 | | - f (rename-properties |
157 | | - {old-p new-p} |
158 | | - {:replace-fn (fn [id prop-value] |
159 | | - (let [page (d/entity db id) |
160 | | - ;; bad impl, it's not just simple db/ident renaming |
161 | | - new-p' (if (ldb/class? page) new-p :block/parent)] |
162 | | - [[:db/retract id old-p] |
163 | | - [:db/add id new-p' prop-value]]))}) |
164 | | - rename-property-tx (f db) |
165 | | - library-page (if-let [page (ldb/get-built-in-page db common-config/library-page-name)] |
166 | | - page |
167 | | - (-> (sqlite-util/build-new-page common-config/library-page-name) |
168 | | - sqlite-create-graph/mark-block-as-built-in)) |
169 | | - library-id (:block/uuid library-page) |
170 | | - library-page-tx (when-not (de/entity? library-page) |
171 | | - [library-page]) |
172 | | - pages-with-parent (->> (d/datoms db :avet :logseq.property/parent) |
173 | | - (keep (fn [d] |
174 | | - (let [e (d/entity db (:e d))] |
175 | | - (when-not (ldb/class? e) |
176 | | - e))))) |
177 | | - parents (->> pages-with-parent |
178 | | - (map :logseq.property/parent) |
179 | | - (common-util/distinct-by :db/id)) |
180 | | - top-parents (remove :logseq.property/parent parents) |
181 | | - top-parent-ids (set (map :db/id top-parents)) |
182 | | - move-top-parents-to-library (map (fn [parent] |
183 | | - {:db/id (:db/id parent) |
184 | | - :block/parent [:block/uuid library-id] |
185 | | - :block/order (db-order/gen-key)}) top-parents) |
186 | | - update-children-parent-and-order (->> pages-with-parent |
187 | | - (remove (fn [page] (top-parent-ids (:db/id page)))) |
188 | | - (map (fn [page] |
189 | | - {:db/id (:db/id page) |
190 | | - :block/order (db-order/gen-key)})))] |
191 | | - (concat |
192 | | - rename-property-tx |
193 | | - library-page-tx |
194 | | - move-top-parents-to-library |
195 | | - update-children-parent-and-order))))) |
196 | | - |
197 | | -(defn- retract-property-attributes |
198 | | - [id] |
199 | | - [[:db/retract id :block/tags :logseq.class/Property] |
200 | | - [:db/retract id :logseq.property/type] |
201 | | - [:db/retract id :db/cardinality] |
202 | | - [:db/retract id :db/valueType] |
203 | | - [:db/retract id :db/index] |
204 | | - [:db/retract id :logseq.property/classes] |
205 | | - [:db/retract id :logseq.property/hide?] |
206 | | - [:db/retract id :logseq.property/public?] |
207 | | - [:db/retract id :logseq.property/view-context] |
208 | | - [:db/retract id :logseq.property/ui-position] |
209 | | - [:db/retract id :logseq.property/default-value] |
210 | | - [:db/retract id :logseq.property/hide-empty-value] |
211 | | - [:db/retract id :logseq.property/enable-history?]]) |
212 | | - |
213 | | -(defn separate-classes-and-properties |
214 | | - [db] |
215 | | - ;; find all properties that're classes, create new properties to separate them |
216 | | - ;; from classes. |
217 | | - (let [class-ids (d/q |
218 | | - '[:find [?b ...] |
219 | | - :where |
220 | | - [?b :block/tags :logseq.class/Property] |
221 | | - [?b :block/tags :logseq.class/Tag]] |
222 | | - db)] |
223 | | - (mapcat |
224 | | - (fn [id] |
225 | | - (let [class (d/entity db id) |
226 | | - ident (:db/ident class) |
227 | | - new-property (sqlite-util/build-new-property |
228 | | - (:block/title class) |
229 | | - (select-keys class [:logseq.property/type :db/cardinality]) |
230 | | - {:title (:block/title class) |
231 | | - :ref-type? true |
232 | | - :properties (merge |
233 | | - (select-keys class [:logseq.property/hide? :logseq.property/public? |
234 | | - :logseq.property/view-context :logseq.property/ui-position |
235 | | - :logseq.property/default-value :logseq.property/hide-empty-value :logseq.property/enable-history?]) |
236 | | - {:logseq.property/classes id})}) |
237 | | - retract-property-attrs (retract-property-attributes id) |
238 | | - datoms (if (:db/index class) |
239 | | - (d/datoms db :avet ident) |
240 | | - (filter (fn [d] (= ident (:a d))) (d/datoms db :eavt))) |
241 | | - tag-properties (->> (d/datoms db :avet :logseq.property.class/properties id) |
242 | | - (mapcat (fn [d] |
243 | | - [[:db/retract (:e d) (:a d) (:v d)] |
244 | | - [:db/add (:e d) (:a d) [:block/uuid (:block/uuid new-property)]]]))) |
245 | | - other-properties-tx (mapcat |
246 | | - (fn [ident] |
247 | | - (->> (d/datoms db :avet ident id) |
248 | | - (mapcat (fn [d] |
249 | | - [[:db/retract (:e d) (:a d) (:v d)] |
250 | | - [:db/add (:e d) (:a d) [:block/uuid (:block/uuid new-property)]]])))) |
251 | | - [:logseq.property.view/group-by-property :logseq.property.table/pinned-columns])] |
252 | | - (concat [new-property] |
253 | | - tag-properties |
254 | | - other-properties-tx |
255 | | - retract-property-attrs |
256 | | - (mapcat |
257 | | - (fn [d] |
258 | | - [[:db/retract (:e d) ident (:v d)] |
259 | | - [:db/add (:e d) (:db/ident new-property) (:v d)]]) |
260 | | - datoms)))) |
261 | | - class-ids))) |
262 | | - |
263 | | -(defn fix-tag-properties |
264 | | - [db] |
265 | | - ;; find all classes that're still used as properties |
266 | | - (let [class-ids (d/q |
267 | | - '[:find [?b ...] |
268 | | - :where |
269 | | - [?b :block/tags :logseq.class/Tag] |
270 | | - [?b1 :logseq.property.class/properties ?b]] |
271 | | - db)] |
272 | | - (mapcat |
273 | | - (fn [id] |
274 | | - (let [class (d/entity db id) |
275 | | - property-id (first (ldb/page-exists? db (:block/title class) :logseq.class/Property)) |
276 | | - tag-properties (when property-id |
277 | | - (->> (d/datoms db :avet :logseq.property.class/properties id) |
278 | | - (mapcat (fn [d] |
279 | | - [[:db/retract (:e d) (:a d) (:v d)] |
280 | | - [:db/add (:e d) (:a d) property-id]]))))] |
281 | | - tag-properties)) |
282 | | - class-ids))) |
283 | | - |
284 | | -(defn add-missing-db-ident-for-tags |
285 | | - [db _sqlite-db] |
286 | | - (let [class-ids (d/q |
287 | | - '[:find [?b ...] |
288 | | - :where |
289 | | - [?b :block/tags :logseq.class/Tag] |
290 | | - [(missing? $ ?b :db/ident)]] |
291 | | - db)] |
292 | | - (mapcat |
293 | | - (fn [id] |
294 | | - [[:db/add id :logseq.property.class/extends :logseq.class/Root] |
295 | | - [:db/retract id :block/tags :logseq.class/Page] |
296 | | - [:db/retract id :block/refs :logseq.class/Page] |
297 | | - [:db/retract id :block/path-refs :logseq.class/Page]]) |
298 | | - class-ids))) |
299 | | - |
300 | | -(defn add-missing-db-ident-for-tags2 |
301 | | - [db] |
302 | | - (let [class-ids |
303 | | - (d/q |
304 | | - '[:find [?b ...] |
305 | | - :where |
306 | | - [?b :block/tags :logseq.class/Tag] |
307 | | - [(missing? $ ?b :db/ident)]] |
308 | | - db)] |
309 | | - (keep |
310 | | - (fn [id] |
311 | | - (let [ent (d/entity db id) |
312 | | - title (:block/title ent) |
313 | | - block-uuid (:block/uuid ent)] |
314 | | - (when block-uuid |
315 | | - {:db-ident-or-block-uuid block-uuid |
316 | | - :new-db-ident (db-ident/replace-db-ident-random-suffix |
317 | | - (db-class/create-user-class-ident-from-name db title) |
318 | | - (subs (str block-uuid) 28))}))) |
319 | | - class-ids))) |
320 | | - |
321 | | -(defn fix-using-properties-as-tags |
322 | | - [db] |
323 | | - ;; find all properties that're tags |
324 | | - (let [property-ids (->> |
325 | | - (d/q |
326 | | - '[:find ?b ?i |
327 | | - :where |
328 | | - [?b :block/tags :logseq.class/Tag] |
329 | | - [?b :db/ident ?i]] |
330 | | - db) |
331 | | - (filter (fn [[_ ident]] (= "user.property" (namespace ident)))) |
332 | | - (map first))] |
333 | | - (mapcat |
334 | | - (fn [id] |
335 | | - (into (retract-property-attributes id) |
336 | | - [[:db/retract id :logseq.property/parent]])) |
337 | | - property-ids))) |
338 | | - |
339 | | -(defn fix-using-properties-as-tags2 |
340 | | - [db] |
341 | | - (let [property-ids |
342 | | - (->> |
343 | | - (d/q |
344 | | - '[:find ?b ?i |
345 | | - :where |
346 | | - [?b :block/tags :logseq.class/Tag] |
347 | | - [?b :db/ident ?i]] |
348 | | - db) |
349 | | - (filter (fn [[_ ident]] (= "user.property" (namespace ident)))) |
350 | | - (map first))] |
351 | | - (keep |
352 | | - (fn [id] |
353 | | - (let [ent (d/entity db id) |
354 | | - title (:block/title ent) |
355 | | - block-uuid (:block/uuid ent)] |
356 | | - (when block-uuid |
357 | | - {:db-ident-or-block-uuid block-uuid |
358 | | - :new-db-ident (db-ident/replace-db-ident-random-suffix |
359 | | - (db-class/create-user-class-ident-from-name db title) |
360 | | - (subs (str block-uuid) 28))}))) |
361 | | - property-ids))) |
362 | | - |
363 | | -(defn remove-block-order-for-tags |
364 | | - [db] |
365 | | - ;; find all properties that're tags |
366 | | - (let [tag-ids (d/q |
367 | | - '[:find [?b ...] |
368 | | - :where |
369 | | - [?b :block/tags :logseq.class/Tag] |
370 | | - [?b :block/order]] |
371 | | - db)] |
372 | | - (map |
373 | | - (fn [id] |
374 | | - [:db/retract id :block/order]) |
375 | | - tag-ids))) |
376 | | - |
377 | | -(defn- update-extends-to-cardinality-many |
378 | | - [db] |
379 | | - (let [extends (d/entity db :logseq.property.class/extends)] |
380 | | - [[:db/add (:db/id extends) :db/cardinality :db.cardinality/many]])) |
381 | | - |
382 | 143 | (defn- add-quick-add-page |
383 | 144 | [_db] |
384 | 145 | (let [page (-> (-> (sqlite-util/build-new-page common-config/quick-add-page-name) |
|
414 | 175 | (when (:logseq.property/ui-position e) |
415 | 176 | [:db/retract (:e d) :logseq.property/ui-position])))))) |
416 | 177 |
|
417 | | -(defn- rename-external-src-to-external-url |
418 | | - [db] |
419 | | - (let [f (rename-properties |
420 | | - {:logseq.property.asset/external-src :logseq.property.asset/external-url} |
421 | | - {})] |
422 | | - (f db))) |
423 | | - |
424 | 178 | (def schema-version->updates |
425 | 179 | "A vec of tuples defining datascript migrations. Each tuple consists of the |
426 | 180 | schema version integer and a migration map. A migration map can have keys of :properties, :classes |
427 | 181 | :rename-db-idents and :fix." |
428 | | - [["65.0" {:fix separate-classes-and-properties}] |
429 | | - ["65.1" {:fix fix-rename-parent-to-extends}] |
430 | | - ["65.2" {:fix fix-tag-properties}] |
431 | | - ["65.3" {:rename-db-idents add-missing-db-ident-for-tags2 :fix add-missing-db-ident-for-tags}] |
432 | | - ["65.4" {:rename-db-idents fix-using-properties-as-tags2 :fix fix-using-properties-as-tags}] |
433 | | - ["65.5" {:fix remove-block-order-for-tags}] |
434 | | - ["65.6" {:fix update-extends-to-cardinality-many}] |
435 | | - ["65.7" {:fix add-quick-add-page}] |
| 182 | + [["65.7" {:fix add-quick-add-page}] |
436 | 183 | ["65.8" {:fix add-missing-page-name}] |
437 | 184 | ["65.9" {:properties [:logseq.property.embedding/hnsw-label-updated-at]}] |
438 | 185 | ["65.10" {:properties [:block/journal-day :logseq.property.view/sort-groups-by-property :logseq.property.view/sort-groups-desc?]}] |
|
441 | 188 | ["65.13" {:properties [:logseq.property.asset/width |
442 | 189 | :logseq.property.asset/height]}] |
443 | 190 | ["65.14" {:properties [:logseq.property.asset/external-src]}] |
444 | | - ["65.15" {:fix rename-external-src-to-external-url}]]) |
| 191 | + ["65.15" (rename-properties {:logseq.property.asset/external-src |
| 192 | + :logseq.property.asset/external-url} |
| 193 | + {})]]) |
445 | 194 |
|
446 | 195 | (let [[major minor] (last (sort (map (comp (juxt :major :minor) db-schema/parse-schema-version first) |
447 | 196 | schema-version->updates)))] |
|
0 commit comments