spark.spec-tacular.datomic

Datomic interface for the spec-tacular DSL

assoc!

(assoc! conn-ctx si & {:as updates})

Updates the given entity in database in the given connection. Returns the new entity.

The entity must be an object representation of an entity on the database (for example, returned from a query, create!, or an earlier assoc!).

Attempting to retract a :component field (by setting that field to nil) retracts the entire component instance.

Get the Datomic :db/id from the object using the :db-ref field.

Aborts if the entity does not exist in the database (use create! instead).

backwards

(backwards spec-name kw)

ConnCtx

A connection context. The only mandatory field is the :conn, which provides the actual connection to the database.

Other option fields include:

  • :transaction-log, any object which can be converted to Datomic transaction data

Connection

count-all-by-spec

(count-all-by-spec db spec)

Returns the number of entities with the given spec in the database.

create!

(create! conn-ctx new-si)

Creates a new instance of the given entity on the database in the given connection context. Returns a representation of the newly created object.

Get the Datomic :db/id from the object using the :db-ref field.

Aborts if the entity already exists in the database (use assoc! instead).

create-graph!

(create-graph! conn-ctx new-si-coll)

Creates every new instance contained in the given collection, and returns the new instances in a collection of the same type, and in the same order where applicable. For every object that is identical? in the given graph, only one instance is created on the database.

create-graph! does not support arbitrarly nested collections.

Currently supports sets, lists, vector, and sequences.

Aborts if any entities already exist on the database.

Database

DatabaseId

db

(db conn-ctx)

Returns the database in a given connection context.

get-all-by-spec

macro

(get-all-by-spec db spec)

Returns all the entities in the database with the given spec.

If the spec is a keyword at compile-time, the resulting entity is cast to the correct type. Otherwise, the resulting entity is a generic SpecInstance

graph-transaction-data

(graph-transaction-data conn-ctx new-si-coll)

Returns Datomic transaction data that would create the given graph on the database given in conn-ctx. Also contains meta-data :tmpids and :specs for the expected temp-ids and specs, respectively.

instance-transaction-data

(instance-transaction-data conn-ctx new-si)

Returns the Datomic transaction data that would create the given spec instance on the database given in conn-ctx.

pull

(pull db pattern instance)

Executes a Datomic pull after datomifying the given pattern with respect to the given instance.

q

macro

(q & stx)

Returns a set of results from the Datomic query. See the README for examples. Also see Datomic’s documentation for query, which we both restrict and expand upon.

(q :find FIND-EXPR+ :in DB-EXPR :where CLAUSE+)

FIND-EXPR   = VAR
            | VAR .
            | (pull VAR pattern)
            | (instance SpecName ?variable)
            | (aggregate expr* VAR)
            | [VAR+ ]
            | [VAR ...]
DB-EXPR     | expr
VAR         = ?variable
            | SpecName
CLAUSE      = SPEC-CLAUSE
            | any otherwise valid Datomic clause
SPEC-CLAUSE = [SpecName SPEC-RHS]
            | [?variable [SpecName SPEC-RHS]]
SPEC-RHS    = % | %n | SpecName
            | {keyword (SPEC-CLAUSE | expr),+}

Every SpecName must be a keyword at compile-time. Every ?variable is quoted, so you do not have to quote them yourself. Anything expr that is not a ?variable or a SpecName is left unchanged (so you can perform operations inside of queries as long as it does not confuse the query syntax).

The FIND-EXPR are used as the :find arguments to the Datomic query. The syntax is the same, except we include (instance SpecName ?variable) for casting any database type to SpecName on its way off the database. This is done automatically for FIND-EXPRS that terminate with SpecNames rather than ?variables. The aggregate function must adhere to Datomic’s requirements: either one of the build-in aggregators or a fully qualified function already imported into the namespace, where the aggregated variable is the final argument.

The value of :in is used as the database; no other arguments to :in are allowed at the moment.

Each :where clause is expanded to one or more Datomic clauses. All Datomic where clause syntax is (intended to be) supported. The SPEC-CLAUSE form finds spec-tacular instances on the database with the fields given in SPEC-RHS.

Using % and %n is analogous to # and % in Clojure: % inserts the first SpecName in the FIND-EXPR if there is only one, or %1 references the first, and %2 the second, etc.

query

added in 0.6.0

(query {find-elems :find, clauses :where, :as m} & args)

Runtime support for spec-tacular queries. Akin to the map syntax for datomic.api/q, this form expects data (rather than syntax), and attempts to unroll spec-tacular maps into valid Datomic :where clauses.

(query {:find FIND-EXPR :in IN-EXPR :where (WHERE-CLAUSE+)} expr+)

FIND-EXPR   = VAR
            | VAR .
            | (spec-pull VAR SpecName spec-tacular-pattern)
            | (pull VAR datomic-pattern)
            | (instance SpecName ?variable)
            | [VAR+ ]
            | [VAR ...]
DB-EXPR     | expr
VAR         = ?variable
            | SpecName
CLAUSE      = SPEC-CLAUSE
            | any otherwise valid Datomic clause
SPEC-CLAUSE = [?variable SPEC-RHS]
SPEC-RHS    | {:spec-tacular/spec SpecName,
               keyword (?variable | constant | spec-instance),+}

Note that SPEC-RHS is no longer recursive via SPEC-CLAUSE. If SpecName names a UnionSpec, we create an or that tries every branch.

If any Exceptions occur enroute, a clojure.lang.ExceptionInfo is thrown with additional information about the query that was executed.

This function uses spark.spec-tacular.datomic.query-helpers in order to datomify the FIND-EXPR and each WHERE-CLAUSE.

refresh

(refresh conn-ctx si)

Returns an updated representation of the Datomic entity at the given instance’s :db-ref.

The entity must be an object representation of an entity on the database (see assoc! for an explanation).

retract!

added in 0.5.1

(retract! conn-ctx si & [field-name])

Removes the given instance from the database using :db.fn/retractEntity. Returns nil.

transaction-log-data

(transaction-log-data conn-ctx)

update!

(update! conn-ctx si-old si-new)

Calculate a shallow difference between the two spec instances and uses assoc! to change the entity on the database.