Sparse-join misses now suppress the nested object (#217), but a parent whose only meaningful content is missing children is still emitted as a hollow shell. Example: a blood-pressure MeasurementObservationSet wrapping systolic + diastolic MeasurementObservations — if neither reading exists, the set still emits with valid identity/constant slots but observations: []. Emitting it asserts "a blood-pressure measurement happened" when nothing was measured (the same silent-shape hazard as #211).
This can't reuse #217's local rule ("object anchored to its populated_from table; no row → no object") because the parent's populated_from row does exist. Suppression here is non-local: it depends on the derived children, and must propagate upward.
Proposed direction:
- Add an opt-in
on_missing: control on a class_derivation (e.g. skip | none | empty), defaulting to current behavior — pruning a parent whose populated_from row exists should never be automatic.
- Pair it with
required_slots: (or similar) to define "empty": the parent is suppressed when its required slots resolve to absent. Needed because constants (observation_type, unit) and parent-derived identity slots (associated_participant) are never null, so "all slots None" is the wrong test — emptiness must be declared, not inferred.
- Suppression cascades: a suppressed parent should let its container re-evaluate its own
required_slots.
Notes:
Origin: design discussion while fixing #217; real-world case from a BDCHM blood-pressure transform.
Sparse-join misses now suppress the nested object (#217), but a parent whose only meaningful content is missing children is still emitted as a hollow shell. Example: a blood-pressure
MeasurementObservationSetwrapping systolic + diastolicMeasurementObservations — if neither reading exists, the set still emits with valid identity/constant slots butobservations: []. Emitting it asserts "a blood-pressure measurement happened" when nothing was measured (the same silent-shape hazard as #211).This can't reuse #217's local rule ("object anchored to its
populated_fromtable; no row → no object") because the parent'spopulated_fromrow does exist. Suppression here is non-local: it depends on the derived children, and must propagate upward.Proposed direction:
on_missing:control on aclass_derivation(e.g.skip | none | empty), defaulting to current behavior — pruning a parent whosepopulated_fromrow exists should never be automatic.required_slots:(or similar) to define "empty": the parent is suppressed when its required slots resolve to absent. Needed because constants (observation_type,unit) and parent-derived identity slots (associated_participant) are never null, so "all slots None" is the wrong test — emptiness must be declared, not inferred.required_slots.Notes:
{value: None}) can emptiness be detected here.Origin: design discussion while fixing #217; real-world case from a BDCHM blood-pressure transform.