|
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