Last active
March 31, 2017 21:40
-
-
Save stuarthalloway/9160152 to your computer and use it in GitHub Desktop.
Complete schema history of a live Datomic database
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; Complete schema history for a live Datomic database. | |
(require | |
'[clojure.pprint :as pp] | |
'[clojure.set :as set] | |
'[datomic.api :as d]) | |
;; fill this in with your own database connection | |
(def uri "datomic:dev://localhost:4334/my-db") | |
(def conn (d/connect uri)) | |
(def db (d/db conn)) | |
;; helpers | |
(def ^java.text.Format formatter (java.text.SimpleDateFormat. "yyyy-MM-dd kk:mm:ss")) | |
(defn format-inst | |
[inst] | |
(.format formatter inst)) | |
(defprotocol Shorten | |
(shorten [_x] "Scrunch things up to fit in a text table")) | |
(extend-protocol Shorten | |
java.lang.Object | |
(shorten [s] s) | |
java.lang.String | |
(shorten [s] (if (< (count s) 20) | |
s | |
(subs s 0 20))) | |
clojure.lang.Keyword | |
(shorten [k] | |
(if (and (namespace k) | |
(.startsWith (namespace k) "db")) | |
(keyword (name k)) | |
k)) | |
java.util.Date | |
(shorten [d] (format-inst d))) | |
(defn schema-history | |
"Returns a map with | |
:op install or alter | |
:entity ident of schema entity | |
:attr ident of schema entity's attribute | |
:val value of attribute | |
:t database time t this fact was recorded | |
:inst wall clock time t this fact was recorded" | |
([db] (schema-history db false)) | |
([db include-bootstrap?] | |
(->> (d/q '[:find ?op ?ent ?attr ?val ?tx | |
:in $ [?op ...] | |
:where | |
[0 ?op ?ent ?tx] | |
[?ent ?attr ?val ?tx]] | |
(d/history db) | |
[:db.install/attribute :db.alter/attribute]) | |
(sort-by #(nth % 4)) | |
(map (fn [[op ent attr v tx]] | |
{:op (case op | |
:db.install/attribute 'install | |
:db.alter/attribute 'alter) | |
:entity (d/ident db ent) | |
:attr (d/ident db attr) | |
:val (if (= :db.type/ref (:value-type (d/attribute db attr))) | |
(d/ident db v) | |
v) | |
:t (d/tx->t tx) | |
:inst (:db/txInstant (d/entity db tx))})) | |
(filter (if include-bootstrap? | |
identity | |
(fn [{:keys [t]}] (>= t 1000))))))) | |
;; data form | |
(schema-history db true) | |
;; print org-mode table of database history | |
(binding [*print-length* nil] | |
(->> (schema-history db true) | |
(map #(reduce | |
(fn [m [k v]] (assoc m k (shorten v))) | |
{} %)) | |
(pp/print-table | |
[:op :entity :attr :val :t :inst]))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment