A namespace for constructing "query slices" or "qslices".
A qslice is a group of datomic query :where clauses with additional metadata related to vars. The point of this metadata is to track where a var's binding is expected to come from and whether any other slice can use the var.
let
)
with their values (as in datomic query :args).
The vars in the binding forms must appear in :where or :provide
and may not appear in :require.Once a qslice is created via qslice
, you may :let-bind any vars in the :where
clause to values via with-let
. Those bindings and values will be
added to the :in and :args of the final compiled query.
(As a convenience, you may also create and bind at the same time by adding
a :let
argument to qslice
)
(Additionally, you can :must-let
vars for safety. This makes it an error
to fail to :let these vars.)
You can also add a cost score to qslices using with-selectivity
to influence clause order.
Lower values will appear earlier in the query.
Once you have a collection of bound qslices,
you can "compile" them to a datomic query using compiled-query
.
This function takes a collection of qslices and "output" forms
(like :find, :with, :keys, etc) and returns a query+args map you can give
to d/query.
The real magic is that vars that are not required or provided in a qslice will be automatically munged in the where clauses that appear in the query so that the same var name will never appear for any other qslice in the set. This means you can write a bunch of qslices independently, with natural-looking :where clauses and possibly the same var names across slices, and combine them into a single query safely without unexpected unification.
You still need to coordinate :provide and :require var contracts among qslices, but the qslice machinery will enforce those contracts come query time.
The public functions of this namespace and their expected call sequence:
qslice
with-name
name
with-selectivity
with-let
with-let*
with-let-locked
let-locked?
compiled-query
compiled-slice-order-names
These are convenience qslice constructors:
db-qslice
rule-qslice
These are qslice "combinators": they accept qslices and return a different one.
or-qslice
A namespace for constructing "query slices" or "qslices". A qslice is a group of datomic query :where clauses with additional metadata related to vars. The point of this metadata is to track where a var's binding is expected to come from and whether any other slice can use the var. * require: Some other query slice must bind this var first. * provide: The clauses bind this var for later query slices later to :require. * let: Binding forms (as in datomic query :in, not clojure destructuring `let`) with their values (as in datomic query :args). The vars in the binding forms must appear in :where or :provide and may not appear in :require. Once a qslice is created via `qslice`, you may :let-bind any vars in the :where clause to values via `with-let`. Those bindings and values will be added to the :in and :args of the final compiled query. (As a convenience, you may also create and bind at the same time by adding a `:let` argument to `qslice`) (Additionally, you can `:must-let` vars for safety. This makes it an error to fail to :let these vars.) You can also add a cost score to qslices using `with-selectivity` to influence clause order. Lower values will appear earlier in the query. Once you have a collection of bound qslices, you can "compile" them to a datomic query using `compiled-query`. This function takes a collection of qslices and "output" forms (like :find, :with, :keys, etc) and returns a query+args map you can give to d/query. The real magic is that *vars that are not required or provided in a qslice will be automatically munged* in the where clauses that appear in the query so that the same var name will never appear for any other qslice in the set. This means you can write a bunch of qslices independently, with natural-looking :where clauses and possibly the same var names across slices, and combine them into a single query safely without unexpected unification. You still need to coordinate :provide and :require var contracts among qslices, but the qslice machinery will enforce those contracts come query time. The public functions of this namespace and their expected call sequence: `qslice` `with-name` `name` `with-selectivity` `with-let` `with-let*` `with-let-locked` `let-locked?` `compiled-query` `compiled-slice-order-names` These are convenience qslice constructors: `db-qslice` `rule-qslice` These are qslice "combinators": they accept qslices and return a different one. `or-qslice`
(compiled-query qslices find-clause)
Compile a collection of qslices into a datomic query-map suitable for d/qseq or d/query (not datomic.api/q).
At least one qslice and a find-clause must be provided. The qslices must all have :let bindings that satisfy their own :must-let, and must satisfy each-other's :provide and :require.
find-clause can be a simple :find vector, or it can be a map with keys :find :with :keys :syms :strs with datomic's meaning. Vars in :find and :with must be :provide-ed by the qslices. (Note that :in and :where are ignored.)
Returns a query map with :query, :args, and :slice-order set.
:slice-order is a vector of maps, one per slice, in the order that the slices were compiled into the query. Each map has:
qslices
collection.Compile a collection of qslices into a datomic query-map suitable for d/qseq or d/query (not datomic.api/q). At least one qslice and a find-clause must be provided. The qslices must all have :let bindings that satisfy their own :must-let, and must satisfy each-other's :provide and :require. find-clause can be a simple :find vector, or it can be a map with keys :find :with :keys :syms :strs with datomic's meaning. Vars in :find and :with must be :provide-ed by the qslices. (Note that :in and :where are ignored.) Returns a query map with :query, :args, and :slice-order set. :slice-order is a vector of maps, one per slice, in the order that the slices were compiled into the query. Each map has: * :slice-idx The index of the slice in the input `qslices` collection. * :name The slice's name. * :selectivity The slice's selectivity value.
(compiled-slice-order-names {:as _compiled-query :keys [slice-order]})
Convenience functions which prints the slice names in :slice-order of a compiled query. Omits names $, %, nil, and empty-string. This is for producing a small, loggable summary of the order of slices in the final query.
Convenience functions which prints the slice names in :slice-order of a compiled query. Omits names $, %, nil, and empty-string. This is for producing a small, loggable summary of the order of slices in the final query.
(db-qslice)
(db-qslice db)
(db-qslice db-sym db)
Return a qslice that provides a datasource (e.g. $).
If called with one argument, $ will be bound to that value.
If called with two arguments, the first argument is the datasource binding
symbol and the second the value (e.g. (db-qslice $h (d/history db))
).
Return a qslice that provides a datasource (e.g. $). If called with one argument, $ will be bound to that value. If called with two arguments, the first argument is the datasource binding symbol and the second the value (e.g. `(db-qslice $h (d/history db))`).
(let-locked? qs)
Returns whether the current qslice was locked via with-let-locked
.
Returns whether the current qslice was locked via `with-let-locked`.
Retrieve the name of a qslice previously set via with-name. The default name of a qslice is the empty string.
Retrieve the name of a qslice previously set via with-name. The default name of a qslice is the empty string.
(or-qslice qslices)
Returns a qslice which behaves as if all the supplied qslices were or-joined together.
Let bindings will be combined, possibly with shading to avoid collisions. The returned qslice will be let-locked. Name will be combined as "or(qslice1 qslice2 ...)". Selectivity will be the minimum found among all input qslices.
There are limitations to what qslices can be combined. All the following conditions must hold or this function will throw:
Returns a qslice which behaves as if all the supplied qslices were or-joined together. Let bindings will be combined, possibly with shading to avoid collisions. The returned qslice will be let-locked. Name will be combined as "or(qslice1 qslice2 ...)". Selectivity will be the minimum found among all input qslices. There are limitations to what qslices can be combined. All the following conditions must hold or this function will throw: * All qslices must provide the exact same vars. * At most one datasource may be required by each qslice. This is a datomic restriction: rules may only access one datasource. * All required datasources must be named $. This is for implementation convenience and could be lifted in the future. * All qslices must-let bindings must be satisfied. This is because you cannot know what the name of the var will be after shading. * No qslices may share owned vars (i.e. vars both provided and must-let). This is for ease of implementation and because the correct semantics for combining their let-bindings is not yet clear.
(qslice &
{:keys [require provide must-let where name selectivity]
let-param :let})
Construct and return a query slice.
Accepts the following arguments as a single map or variadic arguments:
:where
A collection of datomic :where
clauses, as in a datomic query.:let
A collection of pairs of :in binding-forms with their :args value.
You can also provide this after construction using when-let
or when-let*
.:name
An optional name for this slice, default "".
You can also provide this after construction using with-name
.:provide
A collection of datomic vars ($datasources, %, or ?variables)
that this slice will provide via :let, with-let
, or in its :where.
These variables can be used by other slices.:require
A collection of datomic vars that this slice uses but another
slice must :provide.
It automatically includes any datasources or % (if a rule invocation is seen)
found in :where that is not in :provide.:must-let
A collection of datomic vars which must be :let
or
with-let
by this qslice before constructing a datomic query.
Note that datasources or rules in :provide and datasources in :where
but not in :require are automatically added to :must-let because there is
no other way to provide them.Note that this constructor is moderately costly because it performs
form-walking and invariant checks.
Therefore, if the qslice will be reused only with different :name, :let, or
:selectivity values, it is better to construct the base qslice once and modify
it with with-name
, with-let
, with-let*
, or with-selectivity
repeatedly.
Construct and return a query slice. Accepts the following arguments as a single map or variadic arguments: * `:where` A collection of datomic `:where` clauses, as in a datomic query. * `:let` A collection of pairs of :in binding-forms with their :args value. You can also provide this after construction using `when-let` or `when-let*`. * `:name` An optional name for this slice, default "". You can also provide this after construction using `with-name`. * `:provide` A collection of datomic vars ($datasources, %, or ?variables) that this slice will provide via :let, `with-let`, or in its :where. These variables can be used by other slices. * `:require` A collection of datomic vars that this slice uses but another slice must :provide. It automatically includes any datasources or % (if a rule invocation is seen) found in :where that is not in :provide. * `:must-let` A collection of datomic vars which *must* be `:let` or `with-let` by *this* qslice before constructing a datomic query. Note that datasources or rules in :provide and datasources in :where but not in :require are automatically added to :must-let because there is no other way to provide them. * :selectivity An optional long, default 0, which influences the order of this qslice's :where clauses among other qslices in a compiled query. Lower values appear earlier in the query. This is useful to encourage faster or more selective clauses to appear earlier or slower clauses to appear later in the query. Note that this constructor is moderately costly because it performs form-walking and invariant checks. Therefore, if the qslice will be reused only with different :name, :let, or :selectivity values, it is better to construct the base qslice once and modify it with `with-name`, `with-let`, `with-let*`, or `with-selectivity` repeatedly.
(rule-qslice)
(rule-qslice rules)
Return a qslice that provides rules (%). If called with an argument, % will be bound to that value.
Return a qslice that provides rules (%). If called with an argument, % will be bound to that value.
(with-let qs & binding-form->value)
Bind or re-bind values to the qslice.
Arguments after the qslice are alternating binding-forms and values, e.g.:
(with-let the-qslice '?a 1 '[?b ...] 2)
Or a single argument of pairs of binding-forms and value, which will be
delegated to with-let*
. e.g.:
(with-let the-qslice {'?a 1 '[?b ...] 2}) (with-let the-qslice [['?a 1] ['[?b ...] 2]])
with-let
calls do not accumulate: each call completely replaces the
previous :let state of the qslice.
Bind or re-bind values to the qslice. Arguments after the qslice are alternating binding-forms and values, e.g.: (with-let the-qslice '?a 1 '[?b ...] 2) Or a single argument of pairs of binding-forms and value, which will be delegated to `with-let*`. e.g.: (with-let the-qslice {'?a 1 '[?b ...] 2}) (with-let the-qslice [['?a 1] ['[?b ...] 2]]) `with-let` calls do not accumulate: each call completely replaces the previous :let state of the qslice.
(with-let* qs binding-form->value)
Binds values to the qslice. Accepts a seqable of pairs of argument and value.
with-let*
calls do not accumulate: each call completely replaces the
previous :let state of the qslice.
Binds values to the qslice. Accepts a seqable of pairs of argument and value. `with-let*` calls do not accumulate: each call completely replaces the previous :let state of the qslice.
(with-let-locked qs)
Asserts that all must-lets are satisfied and returns a qslice which cannot be with-let again.
This is a utility function for combinators whose behavior would be undefined if the qslice was rebound.
Asserts that all must-lets are satisfied and returns a qslice which cannot be with-let again. This is a utility function for combinators whose behavior would be undefined if the qslice was rebound.
(with-name qs name)
Set a name for this qslice. This is for informational purposes only and does not affect compiled queries.
Set a name for this qslice. This is for informational purposes only and does not affect compiled queries.
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close