Skip to content

Commit e7ccde3

Browse files
author
Christian Weilbach
authored
Merge pull request #1 from bamarco/tx-middleware
transactional schema middleware
2 parents b7aa91f + 1ab7726 commit e7ccde3

File tree

8 files changed

+396
-92
lines changed

8 files changed

+396
-92
lines changed

src/datahike/core.cljc

+5-3
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,11 @@
7575
:tempids {}
7676
:tx-meta tx-meta}) tx-data))))
7777

78-
(defn db-with [db tx-data]
79-
{:pre [(db/db? db)]}
80-
(:db-after (with db tx-data)))
78+
(defn db-with
79+
([db tx-data] (db-with db tx-data nil))
80+
([db tx-data tx-meta]
81+
{:pre [(db/db? db)]}
82+
(:db-after (with db tx-data tx-meta))))
8183

8284
(defn datoms
8385
([db index] {:pre [(db/db? db)]} (db/-datoms db index []))

src/datahike/db.cljc

+57-36
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
data (last fragments)]
3131
`(throw (ex-info (str ~@(map (fn [m#] (if (string? m#) m# (list 'pr-str m#))) msgs)) ~data)))))
3232

33-
(defn #?@(:clj [^Boolean seqable?]
33+
(defn #?@(:clj [^Boolean seqable?]
3434
:cljs [^boolean seqable?])
3535
[x]
3636
(and (not (string? x))
@@ -147,7 +147,7 @@
147147
IIndexed
148148
(-nth [this i] (nth-datom this i))
149149
(-nth [this i not-found] (nth-datom this i not-found))
150-
150+
151151
IAssociative
152152
(-assoc [d k v] (assoc-datom d k v))
153153

@@ -172,7 +172,7 @@
172172
(empty [d] (throw (UnsupportedOperationException. "empty is not supported on Datom")))
173173
(count [d] 5)
174174
(cons [d [k v]] (assoc-datom d k v))
175-
175+
176176
clojure.lang.Indexed
177177
(nth [this i] (nth-datom this i))
178178
(nth [this i not-found] (nth-datom this i not-found))
@@ -191,7 +191,7 @@
191191
([e a v] (Datom. e a v tx0 true))
192192
([e a v tx] (Datom. e a v tx true))
193193
([e a v tx added] (Datom. e a v tx added)))
194-
194+
195195
(defn datom? [x] (instance? Datom x))
196196

197197
(defn- hash-datom [^Datom d]
@@ -468,7 +468,7 @@
468468
(or (> (hc/compare i e) 0)
469469
(> (hc/compare j f) 0)
470470
(> (hc/compare k g) 0)
471-
(> (hc/compare l h) 0))
471+
(> (hc/compare l h) 0))
472472

473473
(and e f g)
474474
(or (> (hc/compare i e) 0)
@@ -775,10 +775,10 @@
775775

776776
(defn ^DB init-db
777777
([datoms] (init-db datoms default-schema))
778-
([datoms schema]
778+
([datoms schema & {:as options :keys [validate?] :or {validate? true}}]
779779
(if (empty? datoms)
780780
(empty-db schema)
781-
(let [_ (validate-schema schema)
781+
(let [_ (when validate? (validate-schema schema))
782782
rschema (rschema schema)
783783
indexed (:db/index rschema)
784784
#?@(:cljs
@@ -945,25 +945,37 @@
945945
(defn entid [db eid]
946946
{:pre [(db? db)]}
947947
(cond
948-
(number? eid) eid
948+
(number? eid)
949+
eid
950+
949951
(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+
963975
: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})))
967979

968980
(defn entid-strict [db eid]
969981
(or (entid db eid)
@@ -1090,10 +1102,10 @@
10901102
(cond
10911103
(keyword? attr)
10921104
(= \_ (nth (name attr) 0))
1093-
1105+
10941106
(string? attr)
10951107
(boolean (re-matches #"(?:([^/]+)/)?_([^/]+)" attr))
1096-
1108+
10971109
:else
10981110
(raise "Bad attribute type: " attr ", expected keyword or string"
10991111
{:error :transact/syntax, :attribute attr})))
@@ -1110,7 +1122,7 @@
11101122
(if (= \_ (nth name 0))
11111123
(if ns (str ns "/" (subs name 1)) (subs name 1))
11121124
(if ns (str ns "/_" name) (str "_" name))))
1113-
1125+
11141126
:else
11151127
(raise "Bad attribute type: " attr ", expected keyword or string"
11161128
{:error :transact/syntax, :attribute attr})))
@@ -1169,12 +1181,12 @@
11691181
(not (or (da/array? vs)
11701182
(and (coll? vs) (not (map? vs)))))
11711183
[vs]
1172-
1184+
11731185
;; probably lookup ref
11741186
(and (= (count vs) 2)
11751187
(is-attr? db (first vs) :db.unique/identity))
11761188
[vs]
1177-
1189+
11781190
:else vs))
11791191

11801192

@@ -1251,7 +1263,7 @@
12511263
(transact-tx-data (assoc-in report [:tempids tempid] upserted-eid)
12521264
es)))
12531265

1254-
(defn transact-tx-data [initial-report initial-es]
1266+
(defn transact-tx-data* [initial-report initial-es]
12551267
(when-not (or (nil? initial-es)
12561268
(sequential? initial-es))
12571269
(raise "Bad transaction data " initial-es ", expected sequential collection"
@@ -1277,13 +1289,13 @@
12771289
(let [id (current-tx report)]
12781290
(recur (allocate-eid report old-eid id)
12791291
(cons (assoc entity :db/id id) entities)))
1280-
1292+
12811293
;; lookup-ref => resolved | error
12821294
(sequential? old-eid)
12831295
(let [id (entid-strict db old-eid)]
12841296
(recur report
12851297
(cons (assoc entity :db/id id) entities)))
1286-
1298+
12871299
;; upserted => explode | error
12881300
[upserted-eid (upsert-eid db entity)]
12891301
(if (and (neg-number? old-eid)
@@ -1292,7 +1304,7 @@
12921304
(retry-with-tempid initial-report initial-es old-eid upserted-eid)
12931305
(recur (allocate-eid report old-eid upserted-eid)
12941306
(concat (explode db (assoc entity :db/id upserted-eid)) entities)))
1295-
1307+
12961308
;; resolved | allocated-tempid | tempid | nil => explode
12971309
(or (number? old-eid)
12981310
(nil? old-eid))
@@ -1301,10 +1313,10 @@
13011313
(neg? old-eid) (or (get (:tempids report) old-eid)
13021314
(next-eid db))
13031315
:else old-eid)
1304-
new-entity (assoc entity :db/id new-eid)]
1316+
new-entity (assoc entity :db/id new-eid)]
13051317
(recur (allocate-eid report old-eid new-eid)
13061318
(concat (explode db new-entity) entities)))
1307-
1319+
13081320
;; trash => error
13091321
:else
13101322
(raise "Expected number or lookup ref for :db/id, got " old-eid
@@ -1392,7 +1404,7 @@
13921404
:else
13931405
(raise "Unknown operation at " entity ", expected :db/add, :db/retract, :db.fn/call, :db.fn/retractAttribute or :db.fn/retractEntity"
13941406
{:error :transact/syntax, :operation op, :tx-data entity})))
1395-
1407+
13961408
(datom? entity)
13971409
(let [[e a v tx added] entity]
13981410
(if added
@@ -1404,6 +1416,15 @@
14041416
{:error :transact/syntax, :tx-data entity})
14051417
))))
14061418

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+
14071428

14081429

14091430
(comment

src/datahike/impl/entity.cljc

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212

1313
(defn- entid [db eid]
1414
(when (or (number? eid)
15-
(sequential? eid))
15+
(sequential? eid)
16+
(keyword? eid))
1617
(db/entid db eid)))
1718

1819
(defn entity [db eid]

0 commit comments

Comments
 (0)