|
30 | 30 | data (last fragments)]
|
31 | 31 | `(throw (ex-info (str ~@(map (fn [m#] (if (string? m#) m# (list 'pr-str m#))) msgs)) ~data)))))
|
32 | 32 |
|
33 |
| -(defn #?@(:clj [^Boolean seqable?] |
| 33 | +(defn #?@(:clj [^Boolean seqable?] |
34 | 34 | :cljs [^boolean seqable?])
|
35 | 35 | [x]
|
36 | 36 | (and (not (string? x))
|
|
147 | 147 | IIndexed
|
148 | 148 | (-nth [this i] (nth-datom this i))
|
149 | 149 | (-nth [this i not-found] (nth-datom this i not-found))
|
150 |
| - |
| 150 | + |
151 | 151 | IAssociative
|
152 | 152 | (-assoc [d k v] (assoc-datom d k v))
|
153 | 153 |
|
|
172 | 172 | (empty [d] (throw (UnsupportedOperationException. "empty is not supported on Datom")))
|
173 | 173 | (count [d] 5)
|
174 | 174 | (cons [d [k v]] (assoc-datom d k v))
|
175 |
| - |
| 175 | + |
176 | 176 | clojure.lang.Indexed
|
177 | 177 | (nth [this i] (nth-datom this i))
|
178 | 178 | (nth [this i not-found] (nth-datom this i not-found))
|
|
191 | 191 | ([e a v] (Datom. e a v tx0 true))
|
192 | 192 | ([e a v tx] (Datom. e a v tx true))
|
193 | 193 | ([e a v tx added] (Datom. e a v tx added)))
|
194 |
| - |
| 194 | + |
195 | 195 | (defn datom? [x] (instance? Datom x))
|
196 | 196 |
|
197 | 197 | (defn- hash-datom [^Datom d]
|
|
468 | 468 | (or (> (hc/compare i e) 0)
|
469 | 469 | (> (hc/compare j f) 0)
|
470 | 470 | (> (hc/compare k g) 0)
|
471 |
| - (> (hc/compare l h) 0)) |
| 471 | + (> (hc/compare l h) 0)) |
472 | 472 |
|
473 | 473 | (and e f g)
|
474 | 474 | (or (> (hc/compare i e) 0)
|
|
775 | 775 |
|
776 | 776 | (defn ^DB init-db
|
777 | 777 | ([datoms] (init-db datoms default-schema))
|
778 |
| - ([datoms schema] |
| 778 | + ([datoms schema & {:as options :keys [validate?] :or {validate? true}}] |
779 | 779 | (if (empty? datoms)
|
780 | 780 | (empty-db schema)
|
781 |
| - (let [_ (validate-schema schema) |
| 781 | + (let [_ (when validate? (validate-schema schema)) |
782 | 782 | rschema (rschema schema)
|
783 | 783 | indexed (:db/index rschema)
|
784 | 784 | #?@(:cljs
|
|
945 | 945 | (defn entid [db eid]
|
946 | 946 | {:pre [(db? db)]}
|
947 | 947 | (cond
|
948 |
| - (number? eid) eid |
| 948 | + (number? eid) |
| 949 | + eid |
| 950 | + |
949 | 951 | (sequential? eid)
|
950 |
| - (cond |
951 |
| - (not= (count eid) 2) |
952 |
| - (raise "Lookup ref should contain 2 elements: " eid |
953 |
| - {:error :lookup-ref/syntax, :entity-id eid}) |
954 |
| - (not (is-attr? db (first eid) :db/unique)) |
955 |
| - (raise "Lookup ref attribute should be marked as :db/unique: " eid |
956 |
| - {:error :lookup-ref/unique |
957 |
| - :entity-id eid}) |
958 |
| - (nil? (second eid)) |
959 |
| - nil |
960 |
| - :else |
961 |
| - (:e (first (-datoms db :avet eid)))) |
962 |
| - #?@(:cljs [(array? eid) (recur db (array-seq eid))]) |
| 952 | + (cond |
| 953 | + (not= (count eid) 2) |
| 954 | + (raise "Lookup ref should contain 2 elements: " eid |
| 955 | + {:error :lookup-ref/syntax, :entity-id eid}) |
| 956 | + (not (is-attr? db (first eid) :db/unique)) |
| 957 | + (if (= :db/ident (first eid)) |
| 958 | + (raise "You must have :db/ident marked as :db/unique in your schema to use keyword refs" {:error :lookup-ref/db-ident |
| 959 | + :entity-id eid}) |
| 960 | + (raise "Lookup ref attribute should be marked as :db/unique: " eid |
| 961 | + {:error :lookup-ref/unique |
| 962 | + :entity-id eid})) |
| 963 | + (nil? (second eid)) |
| 964 | + nil |
| 965 | + :else |
| 966 | + (:e (first (-datoms db :avet eid)))) |
| 967 | + |
| 968 | + #?@(:cljs |
| 969 | + [(array? eid) |
| 970 | + (recur db (array-seq eid))]) |
| 971 | + |
| 972 | + (keyword? eid) |
| 973 | + (recur db [:db/ident eid]) |
| 974 | + |
963 | 975 | :else
|
964 |
| - (raise "Expected number or lookup ref for entity id, got " eid |
965 |
| - {:error :entity-id/syntax |
966 |
| - :entity-id eid}))) |
| 976 | + (raise "Expected number or lookup ref for entity id, got " eid |
| 977 | + {:error :entity-id/syntax |
| 978 | + :entity-id eid}))) |
967 | 979 |
|
968 | 980 | (defn entid-strict [db eid]
|
969 | 981 | (or (entid db eid)
|
|
1090 | 1102 | (cond
|
1091 | 1103 | (keyword? attr)
|
1092 | 1104 | (= \_ (nth (name attr) 0))
|
1093 |
| - |
| 1105 | + |
1094 | 1106 | (string? attr)
|
1095 | 1107 | (boolean (re-matches #"(?:([^/]+)/)?_([^/]+)" attr))
|
1096 |
| - |
| 1108 | + |
1097 | 1109 | :else
|
1098 | 1110 | (raise "Bad attribute type: " attr ", expected keyword or string"
|
1099 | 1111 | {:error :transact/syntax, :attribute attr})))
|
|
1110 | 1122 | (if (= \_ (nth name 0))
|
1111 | 1123 | (if ns (str ns "/" (subs name 1)) (subs name 1))
|
1112 | 1124 | (if ns (str ns "/_" name) (str "_" name))))
|
1113 |
| - |
| 1125 | + |
1114 | 1126 | :else
|
1115 | 1127 | (raise "Bad attribute type: " attr ", expected keyword or string"
|
1116 | 1128 | {:error :transact/syntax, :attribute attr})))
|
|
1169 | 1181 | (not (or (da/array? vs)
|
1170 | 1182 | (and (coll? vs) (not (map? vs)))))
|
1171 | 1183 | [vs]
|
1172 |
| - |
| 1184 | + |
1173 | 1185 | ;; probably lookup ref
|
1174 | 1186 | (and (= (count vs) 2)
|
1175 | 1187 | (is-attr? db (first vs) :db.unique/identity))
|
1176 | 1188 | [vs]
|
1177 |
| - |
| 1189 | + |
1178 | 1190 | :else vs))
|
1179 | 1191 |
|
1180 | 1192 |
|
|
1251 | 1263 | (transact-tx-data (assoc-in report [:tempids tempid] upserted-eid)
|
1252 | 1264 | es)))
|
1253 | 1265 |
|
1254 |
| -(defn transact-tx-data [initial-report initial-es] |
| 1266 | +(defn transact-tx-data* [initial-report initial-es] |
1255 | 1267 | (when-not (or (nil? initial-es)
|
1256 | 1268 | (sequential? initial-es))
|
1257 | 1269 | (raise "Bad transaction data " initial-es ", expected sequential collection"
|
|
1277 | 1289 | (let [id (current-tx report)]
|
1278 | 1290 | (recur (allocate-eid report old-eid id)
|
1279 | 1291 | (cons (assoc entity :db/id id) entities)))
|
1280 |
| - |
| 1292 | + |
1281 | 1293 | ;; lookup-ref => resolved | error
|
1282 | 1294 | (sequential? old-eid)
|
1283 | 1295 | (let [id (entid-strict db old-eid)]
|
1284 | 1296 | (recur report
|
1285 | 1297 | (cons (assoc entity :db/id id) entities)))
|
1286 |
| - |
| 1298 | + |
1287 | 1299 | ;; upserted => explode | error
|
1288 | 1300 | [upserted-eid (upsert-eid db entity)]
|
1289 | 1301 | (if (and (neg-number? old-eid)
|
|
1292 | 1304 | (retry-with-tempid initial-report initial-es old-eid upserted-eid)
|
1293 | 1305 | (recur (allocate-eid report old-eid upserted-eid)
|
1294 | 1306 | (concat (explode db (assoc entity :db/id upserted-eid)) entities)))
|
1295 |
| - |
| 1307 | + |
1296 | 1308 | ;; resolved | allocated-tempid | tempid | nil => explode
|
1297 | 1309 | (or (number? old-eid)
|
1298 | 1310 | (nil? old-eid))
|
|
1301 | 1313 | (neg? old-eid) (or (get (:tempids report) old-eid)
|
1302 | 1314 | (next-eid db))
|
1303 | 1315 | :else old-eid)
|
1304 |
| - new-entity (assoc entity :db/id new-eid)] |
| 1316 | + new-entity (assoc entity :db/id new-eid)] |
1305 | 1317 | (recur (allocate-eid report old-eid new-eid)
|
1306 | 1318 | (concat (explode db new-entity) entities)))
|
1307 |
| - |
| 1319 | + |
1308 | 1320 | ;; trash => error
|
1309 | 1321 | :else
|
1310 | 1322 | (raise "Expected number or lookup ref for :db/id, got " old-eid
|
|
1392 | 1404 | :else
|
1393 | 1405 | (raise "Unknown operation at " entity ", expected :db/add, :db/retract, :db.fn/call, :db.fn/retractAttribute or :db.fn/retractEntity"
|
1394 | 1406 | {:error :transact/syntax, :operation op, :tx-data entity})))
|
1395 |
| - |
| 1407 | + |
1396 | 1408 | (datom? entity)
|
1397 | 1409 | (let [[e a v tx added] entity]
|
1398 | 1410 | (if added
|
|
1404 | 1416 | {:error :transact/syntax, :tx-data entity})
|
1405 | 1417 | ))))
|
1406 | 1418 |
|
| 1419 | +(defn transact-tx-data [{:as initial-report :keys [tx-meta]} initial-es] |
| 1420 | + (let [middleware (or |
| 1421 | + (when (map? tx-meta) |
| 1422 | + (::tx-middleware tx-meta)) |
| 1423 | + identity)] |
| 1424 | + ((middleware transact-tx-data*) |
| 1425 | + initial-report |
| 1426 | + initial-es))) |
| 1427 | + |
1407 | 1428 |
|
1408 | 1429 |
|
1409 | 1430 | (comment
|
|
0 commit comments