github.com/dal-go/dalgo/dtql
DALgo queries as DTQL.
A 1:1, lossless, human-readable YAML serialization of dalgo's
dal.StructuredQuery for the core relational read-only subset. Plain YAML over
the existing query AST — no bespoke grammar, no hand-written parser. Save a
query, hand-edit it, diff it in version control, reload it without loss.
What DTQL represents
A single From over a root collection, the
selected columns, a Where tree, ordering, and paging. Anything out of scope is
rejected with a descriptive error rather than silently dropped.
In scope
Root CollectionRef source · selected Columns ·
Comparison and And/Or GroupCondition trees ·
OrderBy · Limit/Offset. Expressions:
FieldRef, Constant, Array (inline values).
Operators: ==, In, >, >=,
<, <=, And, Or.
Out of scope (rejected)
Joins · CollectionGroupRef or parented CollectionRef ·
GroupBy · aggregate/scalar functions · cursor (StartFrom) ·
any operator outside the in-scope set. Serialization errors out — it never emits a
document that loses query semantics.
Lossless & canonical
deserialize(serialize(q)) is structurally equal to q; serialization
is canonical (stable key order), so serialize(deserialize(d)) is byte-identical
to d and saved queries diff cleanly.
Mapping
Each in-scope dal node has a defined YAML representation.
dal node | YAML representation |
|---|---|
From over root CollectionRef | from: { name, alias? } |
Column | item under columns: — an expression plus optional as: |
Comparison | { op, left, right } |
GroupCondition (And) | { and: [ … ] } |
GroupCondition (Or) | { or: [ … ] } |
OrderExpression | item under orderBy: — an expression plus optional desc: true |
FieldRef | { field: <name> } |
Constant | { value: <scalar> } |
Array | { values: [ <scalar>, … ] } |
Operator | ==, In, >, >=, <, <= |
Limit / Offset | limit: <int> / offset: <int> |
An expression sets exactly one
of field, value or values, which discriminates a
FieldRef, a Constant or an Array.
A query as DTQL
Columns with an alias, a nested And/Or filter with an inline
In array, ordering, and paging.
from:
name: users
columns:
- field: name
- field: age
as: years
where:
and:
- op: '>='
left:
field: age
right:
value: 18
- or:
- op: In
left:
field: status
right:
values:
- active
- pending
- op: ==
left:
field: country
right:
value: US
orderBy:
- field: name
- field: age
desc: true
limit: 10
offset: 20
Validate anywhere
The JSON Schema is generated from the Go types
(the single source of truth) so any tool, in any language, can validate a
.dtql.yaml file.
-
JSON Schema · draft 2020-12
schema.json
The canonical schema.
./schema.json$id:https://dal-go.github.io/dtql/schema.json. -
JSON Schema · YAML
schema.yaml
The same schema, YAML serialization — identical content.
./schema.yaml -
examples
examples/
DTQL documents that each deserialize to a
./examples/dal.StructuredQueryand validate against the schema.
Round-trip fidelity
Structural. For any in-scope query q,
deserialize(serialize(q)) reconstructs a StructuredQuery
structurally equal to q across From, Columns,
Where (including inline Constant/Array values),
OrderBy, Limit and Offset.
Canonical. Serialization is canonical (stable key order, 2-space indent),
so serialize(deserialize(d)) is byte-identical to a valid in-scope document
d — saved queries diff cleanly across edits.