Queries and pull#
Datalog#
Queries are data and take explicit inputs:
(d/q '[:find ?name
:in $ ?active
:where
[?e :person/active ?active]
[?e :person/name ?name]]
db
true)
Supported query features include:
- relation, collection, tuple, and scalar
:find - database and value inputs
- data, predicate, and function clauses
not,not-join,or, andor-join- aggregates
- rules, including recursive rules
- pull expressions in
:find :withand return maps
The EDN frontend accepts vector and map query forms. Native APIs also provide prepared queries and typed result access.
Pull#
Pull returns selected attributes for one or more entities:
(d/pull db
[:person/name
{:person/friends [:person/name]}]
person-id)
Supported patterns include:
- attribute keywords
- wildcard
* - nested joins
- reverse attributes
- recursion limits
:as,:default,:limit, and:xform- lookup refs
Entity reads#
Entity views provide lazy attribute lookup against one immutable database value. Reference attributes can be followed without reading from the live connection.
Use pull when the result shape is known. Use entity views for incremental navigation.
Index reads#
Use datoms, seek-datoms, rseek-datoms, or index-range when index order
is part of the operation. See Data model.
Exact function names and result types vary by package. See the package repository for the host language.
Bounded composite-key pages#
q-page is a deliberately narrow keyset primitive for a query whose only
clause projects [entity, unique-composite-tuple]. It requires a non-empty
proper tuple prefix, uses a strict full-tuple after continuation, and returns
the tuple beside every candidate. The executor reads at most one page plus
lookahead from the current ordered index and, when present, a hard-bounded
SQLite or retained immutable shared overlay. An overlay above the implementation
bound is rejected before it is scanned; unsupported query programs and source
shapes fail instead of falling back to a generic Datalog materialization.
Every returned page includes a stable :error-code keyword independently of
its human-readable :error text. Success uses :none. Failures use one of
:stale-basis, :invalid-request, :unsupported, :storage-error, or
:internal-error. Callers should refresh a pinned continuation only for
:stale-basis; they must not infer error semantics from diagnostic text.
A retained legacy basis which exists but has no :current-avet page is
:unsupported, while SQLite read or corruption failures are :storage-error.
An immutable resident or shared snapshot may be filtered with as-of at its
own exact effective basis; that filter denotes the same snapshot and remains
pageable. An older filtered resident basis is still rejected explicitly because
it requires a versioned retained root. The executor never substitutes current
resident state for historical state.
The version-3 C ABI exports this primitive, and the in-tree Odin and Kvist
packages provide typed/data facades used by native applications. Java,
Clojure, Python, Rust, Go, Node.js, and the CLI do not yet expose a q-page
wrapper. Their ordinary query APIs remain unchanged; ABI-version agreement does
not imply identical high-level package surfaces.