Skip to content

Instantly share code, notes, and snippets.

@cjsauer
Last active June 2, 2018 02:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cjsauer/4dc258cb812024b49fb7f18ebd1fa6b5 to your computer and use it in GitHub Desktop.
Save cjsauer/4dc258cb812024b49fb7f18ebd1fa6b5 to your computer and use it in GitHub Desktop.
Datomic Cloud schema ensure helpers
(ns datomic-ensure
(:require [datomic.client.api :as d]))
(defn cardinality
"Returns the cardinality (:db.cardinality/one or
:db.cardinality/many) of the attribute"
[db attr]
(->>
(d/q '[:find ?v
:in $ ?attr
:where
[?attr :db/cardinality ?card]
[?card :db/ident ?v]]
db attr)
ffirst))
(defn has-attribute?
"Does database have an attribute named attr-name?"
[db attr-name]
(-> (d/pull db '[*] attr-name)
:db/id
boolean))
(defn has-schema?
"Does database have a schema named schema-name installed?
Uses schema-attr (an attribute of transactions!) to track
which schema names are installed."
[db schema-attr schema-name]
(and (has-attribute? db schema-attr)
(-> (d/q '[:find ?e
:in $ ?sa ?sn
:where [?e ?sa ?sn]]
db schema-attr schema-name)
seq boolean)))
(defn- ensure-schema-attribute
"Ensure that schema-attr, a keyword-valued attribute used
as a value on transactions to track named schemas, is
installed in database."
[conn schema-attr]
(when-not (has-attribute? (d/db conn) schema-attr)
(d/transact conn {:tx-data [{:db/ident schema-attr
:db/valueType :db.type/keyword
:db/cardinality :db.cardinality/one
:db/doc "Name of schema installed by this transaction"}]})))
(defn ensure-schemas
"Ensure that schemas are installed.
schema-attr a keyword valued attribute of a transaction,
naming the schema
schema-map a map from schema names to schema installation
maps. A schema installation map contains two
keys: :txes is the data to install, and :requires
is a list of other schema names that must also
be installed
schema-names the names of schemas to install"
[conn schema-attr schema-map & schema-names]
(ensure-schema-attribute conn schema-attr)
(doseq [schema-name schema-names]
(when-not (has-schema? (d/db conn) schema-attr schema-name)
(let [{:keys [requires txes]} (get schema-map schema-name)]
(apply ensure-schemas conn schema-attr schema-map requires)
(if txes
(d/transact conn {:tx-data (conj txes {schema-attr schema-name})})
(throw (ex-info (str "No data provided for schema" schema-name)
{:schema/missing schema-name})))))))
(ns my-project.core
(:require [datomic.client.api :as d]
[datomic-ensure :refer [ensure-schemas]]))
;; Set up Datomic connection...
(def system-name "system-name")
(def region "us-east-1")
(def db-name "db-name")
(def cfg {:server-type :cloud
:region region
:system system-name
:query-group system-name
:endpoint (format "http://entry.%s.%s.datomic.net:8182/" system-name region)
:proxy-port 8182})
(def client (d/client cfg))
(d/create-database client {:db-name db-name})
(def conn (d/connect client {:db-name db-name}))
(def schema-map
{::db-schema
{:txes [{:db/ident :person/uuid
:db/valueType :db.type/uuid
:db/cardinality :db.cardinality/one}]}
;; Schemas can depend on each other
::other-schema
{:txes [{:db/ident :something/else
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one}]
:requires [::db-schema]}})
;; Ensure all schemas
(apply ensure-schemas conn :datomic-ensure/schema schema-map (keys schema-map))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment