Skip to content

Commit a9501cc

Browse files
committed
feat: transact db schema as tx-data
1 parent fc3645f commit a9501cc

File tree

2 files changed

+70
-13
lines changed

2 files changed

+70
-13
lines changed

src/datascript/db.cljc

Lines changed: 66 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
[clojure.walk]
55
[clojure.data]
66
#?(:clj [datascript.inline :refer [update]])
7+
[datascript.schema :as ds]
78
[datascript.lru :as lru]
89
[me.tonsky.persistent-sorted-set :as set]
910
[me.tonsky.persistent-sorted-set.arrays :as arrays])
@@ -887,7 +888,7 @@
887888
{}
888889
(:db.type/tuple rschema)))
889890

890-
(defn- rschema
891+
(defn- rschema [schema]
891892
":db/unique => #{attr ...}
892893
:db.unique/identity => #{attr ...}
893894
:db.unique/value => #{attr ...}
@@ -897,17 +898,18 @@
897898
:db/isComponent => #{attr ...}
898899
:db.type/tuple => #{attr ...}
899900
:db/attrTuples => {attr => {tuple-attr => idx}}"
900-
[schema]
901901
(let [rschema (reduce-kv
902-
(fn [rschema attr attr-schema]
903-
(reduce-kv
904-
(fn [rschema key value]
902+
(fn [m attr keys->values]
903+
(if (keyword? keys->values)
904+
m
905+
(reduce-kv
906+
(fn [m key value]
905907
(reduce
906-
(fn [rschema prop]
907-
(update rschema prop conjs attr))
908-
rschema (attr->properties key value)))
909-
rschema attr-schema))
910-
{} schema)]
908+
(fn [m prop]
909+
(assoc m prop (conj (get m prop #{}) attr)))
910+
m (attr->properties key value)))
911+
(update m :db/ident (fn [coll] (if coll (conj coll attr) #{attr}))) keys->values)))
912+
{} schema)]
911913
(assoc rschema :db/attrTuples (attr-tuples schema rschema))))
912914

913915
(defn- validate-schema-key [a k v expected]
@@ -1271,25 +1273,76 @@
12711273
true
12721274
(update :db-after advance-max-eid eid))))
12731275

1276+
(defn remove-schema [db ^Datom datom]
1277+
(let [schema (:schema db)
1278+
e (.-e datom)
1279+
a (.-a datom)
1280+
v (.-v datom)
1281+
a-ident a
1282+
v-ident v]
1283+
(if (= a-ident :db/ident)
1284+
(if-not (schema v-ident)
1285+
(let [err-msg (str "Schema with attribute " v-ident " does not exist")
1286+
err-map {:error :retract/schema :attribute v-ident}]
1287+
(throw #?(:clj (ex-info err-msg err-map)
1288+
:cljs (error err-msg err-map))))
1289+
(-> (assoc-in db [:schema e] (dissoc (schema v-ident) a-ident))
1290+
(update-in [:schema] #(dissoc % v-ident))
1291+
(update-in [:ident-ref-map] #(dissoc % v-ident))
1292+
(update-in [:ref-ident-map] #(dissoc % e))))
1293+
(if-let [schema-entry (schema e)]
1294+
(if (schema schema-entry)
1295+
(update-in db [:schema schema-entry] #(dissoc % a-ident))
1296+
(update-in db [:schema e] #(dissoc % a-ident v-ident)))
1297+
(let [err-msg (str "Schema with entity id " e " does not exist")
1298+
err-map {:error :retract/schema :entity-id e :attribute a :value e}]
1299+
(throw #?(:clj (ex-info err-msg err-map)
1300+
:cljs (error err-msg err-map))))))))
1301+
1302+
(defn get-schema [db]
1303+
(or (:schema db) {}))
1304+
1305+
(defn update-schema [db ^Datom datom]
1306+
(let [schema (get-schema db)
1307+
e (.-e datom)
1308+
a (.-a datom)
1309+
v (.-v datom)
1310+
a-ident a
1311+
v-ident v]
1312+
(if (= a-ident :db/ident)
1313+
(if (schema v-ident)
1314+
(raise (str "Schema with attribute " v-ident " already exists")
1315+
{:error :transact/schema :attribute v-ident})
1316+
(assoc-in db [:schema v-ident a-ident] v-ident))
1317+
(let [e-ident (:v (first (-seek-datoms db :eavt e :db/ident nil nil)))]
1318+
(assoc-in db [:schema e-ident a-ident] v-ident)))))
1319+
1320+
(defn update-rschema [db]
1321+
(assoc db :rschema (rschema (get-schema db))))
1322+
12741323
;; In context of `with-datom` we can use faster comparators which
12751324
;; do not check for nil (~10-15% performance gain in `transact`)
12761325

12771326
(defn with-datom [db ^Datom datom]
12781327
(validate-datom db datom)
1279-
(let [indexing? (indexing? db (.-a datom))]
1328+
(let [indexing? (indexing? db (.-a datom))
1329+
schema? (ds/schema-attr? (.-a datom))]
12801330
(if (datom-added datom)
12811331
(cond-> db
12821332
true (update :eavt set/conj datom cmp-datoms-eavt-quick)
12831333
true (update :aevt set/conj datom cmp-datoms-aevt-quick)
12841334
indexing? (update :avet set/conj datom cmp-datoms-avet-quick)
12851335
true (advance-max-eid (.-e datom))
1286-
true (assoc :hash (atom 0)))
1336+
true (assoc :hash (atom 0))
1337+
schema? (-> (update-schema datom)
1338+
update-rschema))
12871339
(if-some [removing (fsearch db [(.-e datom) (.-a datom) (.-v datom)])]
12881340
(cond-> db
12891341
true (update :eavt set/disj removing cmp-datoms-eavt-quick)
12901342
true (update :aevt set/disj removing cmp-datoms-aevt-quick)
12911343
indexing? (update :avet set/disj removing cmp-datoms-avet-quick)
1292-
true (assoc :hash (atom 0)))
1344+
true (assoc :hash (atom 0))
1345+
schema? (-> (remove-schema datom) update-rschema))
12931346
db))))
12941347

12951348
(defn- queue-tuple [queue tuple idx db e a v]

src/datascript/schema.cljc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
(ns datascript.schema)
2+
3+
(defonce schema-attr?
4+
#{:db/id :db/ident :db/isComponent :db/valueType :db/cardinality :db/unique :db/index :db/doc :db/tupleAttrs :db/tupleType :db/tupleTypes})

0 commit comments

Comments
 (0)