Multi-sized results¶
Some rules can produce more than one output value per input record. This fans the execution out: every downstream rule in the chain runs once per result, and the source row produces multiple CDM rows.
The [] and [N] suffixes¶
| Suffix | Meaning |
|---|---|
[] |
Unbounded — produce as many output rows as the rule returns matches. |
[N] |
Exactly N results required. If fewer are available, the row is skipped and an error is logged. |
UsagiMap("file.csv")[] # variable number of results
UsagiMap("file.csv")[3] # exactly 3 results required
LoopOver controls the cartesian product¶
When several fields produce multi-sized results, the engine needs to know
how to combine them. The LoopOver
table rule declares this at the CDM-table level:
- Fields in the same array are zipped — the i-th result of one is paired with the i-th result of the others.
- Fields in different arrays form a cartesian product.
LoopOver([:field_one])
LoopOver([:field_one, :field_two])
LoopOver([:field_one, :field_two], [:cartesian_field_three])
Any mapping with a multi-sized result must declare LoopOver, even if only
one field is multi-sized.
Forking and converging execution paths¶
A multi-sized rule forks the execution path. Successive multi-sized rules
multiply forks, so the engine may end up tracking many parallel (var1, var2,
…) tuples per source row. Subsequent aggregations such as
Unique can be used as a
convergence point: every fork's value is collected, deduplicated, and
the chain refurnishes one fork per unique value.
Don't put Unique inside a conditional branch
If some forks reach Unique and others don't, the post-Unique state
is inconsistent — some forks see the converged value, others the
original variables. This is rarely what you want.