|
4 | 4 | [clojure.walk]
|
5 | 5 | [clojure.data]
|
6 | 6 | #?(:clj [datascript.inline :refer [update]])
|
| 7 | + [datascript.schema :as ds] |
7 | 8 | [datascript.lru :as lru]
|
8 | 9 | [me.tonsky.persistent-sorted-set :as set]
|
9 | 10 | [me.tonsky.persistent-sorted-set.arrays :as arrays])
|
|
887 | 888 | {}
|
888 | 889 | (:db.type/tuple rschema)))
|
889 | 890 |
|
890 |
| -(defn- rschema |
| 891 | +(defn- rschema [schema] |
891 | 892 | ":db/unique => #{attr ...}
|
892 | 893 | :db.unique/identity => #{attr ...}
|
893 | 894 | :db.unique/value => #{attr ...}
|
|
897 | 898 | :db/isComponent => #{attr ...}
|
898 | 899 | :db.type/tuple => #{attr ...}
|
899 | 900 | :db/attrTuples => {attr => {tuple-attr => idx}}"
|
900 |
| - [schema] |
901 | 901 | (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] |
905 | 907 | (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)] |
911 | 913 | (assoc rschema :db/attrTuples (attr-tuples schema rschema))))
|
912 | 914 |
|
913 | 915 | (defn- validate-schema-key [a k v expected]
|
|
1271 | 1273 | true
|
1272 | 1274 | (update :db-after advance-max-eid eid))))
|
1273 | 1275 |
|
| 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 | + |
1274 | 1323 | ;; In context of `with-datom` we can use faster comparators which
|
1275 | 1324 | ;; do not check for nil (~10-15% performance gain in `transact`)
|
1276 | 1325 |
|
1277 | 1326 | (defn with-datom [db ^Datom datom]
|
1278 | 1327 | (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))] |
1280 | 1330 | (if (datom-added datom)
|
1281 | 1331 | (cond-> db
|
1282 | 1332 | true (update :eavt set/conj datom cmp-datoms-eavt-quick)
|
1283 | 1333 | true (update :aevt set/conj datom cmp-datoms-aevt-quick)
|
1284 | 1334 | indexing? (update :avet set/conj datom cmp-datoms-avet-quick)
|
1285 | 1335 | 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)) |
1287 | 1339 | (if-some [removing (fsearch db [(.-e datom) (.-a datom) (.-v datom)])]
|
1288 | 1340 | (cond-> db
|
1289 | 1341 | true (update :eavt set/disj removing cmp-datoms-eavt-quick)
|
1290 | 1342 | true (update :aevt set/disj removing cmp-datoms-aevt-quick)
|
1291 | 1343 | 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)) |
1293 | 1346 | db))))
|
1294 | 1347 |
|
1295 | 1348 | (defn- queue-tuple [queue tuple idx db e a v]
|
|
0 commit comments