Skip to content

fix(search): contain the #534 abstract-prefix strip — _in/_language activation, conditional-write typing #535

Description

@angela-helios

Findings from the #534 review (part 1, part 2), filed so they survive however #534 lands. Root cause of the top three: the abstract-prefix strip activates every Resource.-prefixed spec expression, not only the audited meta set.

Blocking-grade

  1. _in (R5/R6) indexes wrong data: expression Resource.id now evaluates, so every resource writes its own id as an _in reference row. GET /Patient?_in=42 returns Patient/42 via the bare-id reference branch — List membership never checked. Pre-fix(search): index _source instead of evaluating Resource.meta.source #534 the parameter was inert. One junk row per resource per reindex.
  2. _language (R5/R6) diverges by backend: newly indexed; Postgres filters via the token path, SQLite routes it to build_special_parameter_condition's _ => None arm (missing from the exemption list at query_builder.rs:391-398) and silently drops the filter — every resource returned. The search: _tag, _profile and _security filters are silently dropped — even under Prefer: handling=strict — and the self link claims they were applied #474 failure mode, reintroduced for a parameter fix(search): index _source instead of evaluating Resource.meta.source #534 activates.
  3. Conditional writes duplicate on _source: CompositeStorage::infer_conditional_param_type (composite/storage.rs:213) types _source as String while the extractor writes Uri rows — If-None-Exist: Patient?_source=http://x queries value_string, never matches, creates a duplicate every time. Same gap in the registry-miss fallbacks of postgres/sqlite build_search_parameters (_tag|_profile|_security → Token, no _source → Uri).

Correctness, lower severity

  1. String-literal | inside a Resource.-prefixed union member: the '|'-split runs before stripping, the stripped fragment is unbalanced, evaluate_fhirpath errors, and extraction of all members of that parameter aborts (pre-fix(search): index _source instead of evaluating Resource.meta.source #534, concrete members survived).
  2. Parenthesized (Resource.meta.source) still extracts nothing silently (same search: _source is never indexed, so _source searches match nothing on PG/Mongo/ES (and everything on SQLite) #523 symptom).
  3. The DomainResource half of ABSTRACT_BASE_TYPES is unreachable for base: ["DomainResource"] definitions — extract() only consults the concrete-type and Resource registry buckets.
  4. No reindex note: pre-upgrade resources have no _source rows; ?_source= misses older data until $reindex.

Robustness / cleanup

  1. Loader test bounds are one-sided (<= 10 passes if fallbacks are lost; .find() accepts feature-gated duplicates) — derive the count from load_embedded().len().
  2. ABSTRACT_BASE_TYPES is a third hand-copy of the abstract-base set (also SearchParameterDefinition::applies_to, ui/editor.rs:527) — hoist to one shared item.
  3. strip_abstract_base_prefix can return Option<&str> and keep the closure zero-alloc; deeper root cause is the FHIRPath evaluator resolving leading type identifiers by exact match only (no subsumption), which fix(search): index _source instead of evaluating Resource.meta.source #534 patches in one consumer.

Suggested containment for 1-2: limit the strip to the audited meta parameters, or handle/exclude _in and _language explicitly in the same change.

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