Skip to content

search: token :not is per-row, not per-resource — wrong on every nested/array-valued parameter #473

Description

@angela-helios

Found by the #448 sweep v2 (SQLite, Synthea data): a coherence matrix over every positively-matched parameter shows :not fails on 19 of 19 token parameters whose values live in nested or array elements, while top-level scalars behave.

Evidence (all manually re-verified)

Query = total :not total Expected :not Cohort
Patient?gender:not=male (top-level scalar) 16 11 11 27 — ✅ correct
`Patient?language:not=urn:ietf:bcp:47 en-US` 24 27 ≤3
`Observation?combo-code:not=http://loinc.org 8302-2` 85 1400 1315
ExplanationOfBenefit?status:not=active 514 (all) 1 0 514 — one phantom row
`Encounter?reason-code:not=sct 36971009` 3 245 ≥370
MedicationAdministration?reason-given:not=… 9 9 16 25 — returns the matches

…plus 13 more in the sweep output (PractitionerRole specialty/role/telecom, Organization/Device type, Immunization vaccine-code, identifiers, DiagnosticReport category, Provenance agent-type, SearchParameter target).

Reading the shapes

FHIR :not means no value of the parameter equals X — per resource, and resources without the element count as matches. The observed behaviors fit a per-row predicate on the search index join (EXISTS(row != X) or plain value != X on a multi-row join) instead of NOT EXISTS(row = X):

  • multi-row resources leak in whenever any of their rows differs (category arrays, codings),
  • resources with no rows for the param drop out entirely (Encounter reason-code),
  • the EOB oddity (all 514 active yet :not finds 1) suggests an extra indexed row from a contained resource satisfying the !=.

The gender case passes only because single top-level scalars have exactly one row.

Part of the #448 sanity pass, iteration 2. Likely home: the sqlite token modifier handling (modifier_handlers.rs / token handler) — same neighborhood as the #456 date fix.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions