This Clojure library provides custom types for your Datomic attributes. It does this by wrapping a leaky abstraction around your regular Datomic API.
Add custom types by implementing the serialize
, deserialize
and
get-backing-datomic-type
multimethods in the datomic-type-extensions.types
namespace.
Require [datomic-type-extensions.api :as d]
instead of [datomic.api :as d]
.
When you d/connect
the first time, a :dte/valueType
attribute will be
installed.
Assert :dte/valueType
for your typed attributes. When transacting attribute
definitions, the original :db/valueType
will be added by looking it up in
get-backing-datomic-type
.
When using d/transact
, d/transact-async
or d/with
, your typed attributes
will be serialized before being passed to Datomic.
When using d/q
, d/query
, d/pull
or d/pull-many
, your typed attributes will be
deserialized on the way out of Datomic.
Entities returned by d/entity
will lazily deserialize their types.
Oh, the convenience!
Oh yes. Let's look at some ways this abstraction leaks:
Database functions see serialized values.
Where-clauses in queries see serialized values.
Params to queries are not serialized for you.
Datoms (as returned by :tx-data
, indexes, and the log) are not
deserialized.
I bet there are more! This abstraction is leaky and under-tested. You probably do not want to use this library yet.
Define a custom type:
(require '[datomic-type-extensions.types :as types])
(defmethod types/get-backing-datomic-type
:java.time/instant [_]
:db.type/instant)
(defmethod types/serialize
:java.time/instant [_ ^Instant instant]
(java.util.Date/from instant))
(defmethod types/deserialize
:java.time/instant [_ ^java.util.Date inst]
(Instant/ofEpochMilli (.getTime inst)))
If you're interested in storing java.time types in Datomic, use java-time-dte.
Then use the custom type:
(require '[datomic-type-extensions.api :as d])
(defn create-conn []
(let [url (str "datomic:mem://" (d/squuid))]
(d/create-database url)
(d/connect url)))
(def conn (create-conn))
@(d/transact
conn
[{:db/ident :user/email
:db/valueType :db.type/string
:db/unique :db.unique/identity
:db/cardinality :db.cardinality/one}
{:db/ident :user/created-at
:dte/valueType :java.time/instant ;; here's the typed attribute
:db/cardinality :db.cardinality/one}])
@(d/transact
conn
[{:user/email "foo@example.com"
:user/created-at (java.time.Instant/parse "2017-01-01T00:00:00Z")}])
(d/pull (d/db conn)
[:user/created-at]
[:user/email "foo@example.com"]) ;; :user/created-at is a java.time.Instant
(:user/created-at (d/entity (d/db conn) [:user/email "foo@example.com"]))
;; => returns a java.time.Instant
(d/q '[:find ?inst . :where [_ :user/created-at ?inst]]
(d/db conn)) ;; so does this
(let [[[e a v]]
(seq (d/datoms (d/db conn) :eavt [:user/email "foo@example.com"] :user/created-at))]
v) ;; this leaks: it returns a java.util.Date (the serialized backing type)
Some of these I hope to correct. But most of all I hope that this entire library will be made redundant by the Datomic team.
Since Conformity's ensure-conforms
transacts for you using the non-wrapped
Datomic API, you can add the backing types like so:
(d/add-backing-types tx-data)
before sending the migrations to Conformity.
If you are also migrating in data that needs to be serialized, you might have to do the attribute migrations first, and then do:
(d/prepare-tx-data db tx-data)
on the data migration.
Add [datomic-type-extensions "2019-09-04"]
to :dependencies
in your project.clj
.
datomic.api/history
to ensure we cache the type extended
attributes before the history db makes us unable to find them.datomic.api/filter
to ensure we cache the type extended
attributes before you filter them out of the database.Bugfixes:
Bugfixes:
Bugfixes:
Bugfixes / aligning the APIs with Datomic:
Copyright © Anders Furseth and Magnar Sveen, since 2018
Distributed under the Eclipse Public License, the same as Clojure.
Can you improve this documentation? These fine people already did:
Magnar Sveen & Anders FursethEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close