meta::column and the statement’s row typeOpen and answer this issue on GitHub.
language, libraries, ready · opened 2026-09-30 · updated 2026-10-06 · 2 comments
Step 1 of ADR-143 §5. A grammar declares a result column with meta::column(name, type), the third and last intrinsic of the hybrid binding; the compiler derives the statement’s row type from the declared columns, as it derives the parameter type from the holes. Today a dsl block’s holes come from a scan of the body text (crates/nikaia/src/dsl.rs, which its own note calls an approximation); meta::parameter waits on the same machinery.
The harness it waited on is built (ADR-177: the grammar’s generated parser is compiled and run during the build). What comes back must be a flat list of declared columns and parameters, one of the five shapes that cross.
Steps 1 and 3 are one piece of work with ADR-254: the row type cannot be run without an execute, and the connection is the statement’s subject.
9d47c62)meta::column / meta::parameter / meta::capture exists in the compiler. dsl.rs still finds holes by scanning the text."created-at".comptime (ADR-287/311), reflection (ADR-304: field.name, field.of(v), no field.type), and grammar runs (ADR-177). meta::column is the first channel that goes from data to a type.anytype. Nothing in it is about creating a type from data. The relevant principle is that a message must point at something someone wrote, and D4 of the new record keeps it.std::meta::Type is an enum: I64, I32, U8, U64, U32, F64, Bool, Text, Bytes, Maybe(Type), List(Type), Record(Vec[Field]), Named(ref String).meta::column(name, ty) and meta::parameter(name, ty) take one.Named is resolved where the block stands, and an unknown name gives NK1135.--comptime prints each block’s type.ADR-299 D12–D14:
u.a.id, u.name.NK1107, and the help names the qualified paths and AS.AS. The compiler never renames.Specification: Part II 10.5, Part III NK1107.
Not decided: whether two blocks with the same columns share one type, or each block gets its own (ADR-323 §6). Asked of the owner now; build each block its own type until answered (the safe direction).
execute)std::meta. Type and Field as above, in std’s Nikaia half. The recursive variant needs #97’s boxing; until then, build the scalars and Maybe, and mark the rest.meta::column / meta::parameter in a grammar run. Callable from a grammar’s actions at build time. The calls are recorded and handed back beside the rule’s result, through ADR-177 D4’s crossing; Type values cross as enum variants (ADR-311).dsl block whose grammar declared columns, write a struct: one field per table group holding that table’s columns, plus the flat fields from D12–D13. Map Text→String, Maybe(t)→t?, the numeric types and Bytes.dsl.rs’s text scan with the declared parameters, and feed ADR-296 D5’s struct with them.u.emial gives NK1107, naming the block (line) and the declared fields.u.id when two tables have id gives NK1107, and the help names u.a.id, u.b.id and AS.Named("Nope") gives NK1135 at the block, naming the grammar.--comptime prints the row and parameter types of each block.T? for Maybe, a duplicate name across two groups, and a refusal from the grammar for a bad column name.Generated by Claude Code
Decided: a block may name the struct its rows are
dsl … -> T { … } eod. The rules, all decided by the owner:
extra_columns / missing_fields, which belong to the compiler;NULL goes only into T?, and a NULL at run time is a named error;Shared[T] fields are refused until #475.Records: ADR-299 D15-D19, Part II 10.5, NK1218-NK1223. Build: #477.
Still open: a column of one number type into a field of another.
Generated by Claude Code