#Master Data Relations
This document defines master-to-master references. The ref<M> field also drives the per-field Join builder on the source query — see Join Operator. Richer relation contracts (cardinality, cascade behavior) will be defined in future revisions of this document.
#Reference Type
A ref<M> value identifies one row of a master M by its primary key.
master A {
record {
primary id: int,
primary name: string,
}
}
master B {
record {
primary id: int,
aRecord: ref<A>,
}
}
ref is a built-in generic type with one type argument. The argument must be a master type; any other argument is reported as masterbelt.checker.ref_non_master_target.
#Field Expansion
A field whose type is ref<M> is expanded into the target master's primary-key fields. The expanded fields are introduced at the parent record's top level, named by joining the original field name and the target's primary-key field name with _.
For the example above, master B's effective record shape is:
B.id : int
B.aRecord_id : int
B.aRecord_name: string
The expansion is observable at every consumer of the schema:
- CSV import: source files must provide one column per expanded field. The example expects
id, aRecord_id, aRecord_name. - Code generation: the target language emits one field per expanded entry on the generated record type, and emits a per-field Join builder that resolves the ref's expanded primary-key columns against the target master's relation through
FindBy(see Join Operator).
The original ref field name does not appear as a single nested field at any consumer in the current revision.
#Post-Filter Collections in Validation
The same post-filter record collection that source programs reach through Master.toList() also appears as the table binding (and its alias self) of a master's validation all rule, iterated with for row in table. The only source-level relation terminal is toList(); findBy and the other terminals stay codegen/runtime-level. The relation stage operators (where, orderBy, thenBy, skip, take) are reachable from source only inside a scope body, where a validation all rule may also call the master's scopes on table.
#Reserved Keywords
The identifier ref is not reserved: it is matched only when written as a generic type argument application ref<M>. Using ref as an ordinary identifier elsewhere remains allowed.