Skip to content

Support the logical OR (comma separated values) for FHIR search parameters#555

Open
schwzr wants to merge 1 commit into
developfrom
issue/554_Support_FHIR_Search_OR
Open

Support the logical OR (comma separated values) for FHIR search parameters#555
schwzr wants to merge 1 commit into
developfrom
issue/554_Support_FHIR_Search_OR

Conversation

@schwzr

@schwzr schwzr commented Jul 26, 2026

Copy link
Copy Markdown
Member

Closes #554

Summary

Implements the FHIR search OR join: comma separated values within a single search parameter are combined with a logical OR, while separately repeated parameters keep the existing logical AND semantics, per https://www.hl7.org/fhir/search.html#combining

  • GET [base]/[type]?param=a,b → resources matching a OR b
  • GET [base]/[type]?param=a&param=b → resources matching a AND b (unchanged)

Implementation

The combination is applied centrally in SearchQuery, so the ~40 individual search parameter type implementations are left untouched. A single comma separated value is split into an OR-group of parameter instances; the group's filter fragments are combined with OR, the groups (and the read-access filter) with AND. The same grouping is applied to:

  • the generated SQL filter — ( <frag1> OR <frag2> ... ), one query with N bound parameters (PostgreSQL combines the GIN index scans via BitmapOr, no extra round-trips),
  • the in-memory matcher used for Subscriptions (a resource matches a group if it matches any of the OR values),
  • the search bundle self link (OR values kept comma separated within one parameter, AND values as repeated parameters).

A comma escaped as \, is treated as a literal character (and unescaped); the other FHIR escape sequences (\|, \$, \\) are left for the parameter type specific parsing (unchanged behavior).

For a value without a comma the OR-group has a single member and the emitted SQL fragment is byte-identical to before — so existing searches are unaffected.

Scope

In scope: OR (comma) combination for all search parameter types (token, string, reference, date, number, quantity, uri, _id, _lastUpdated, _profile, _tag, ...), \, escaping, correct self link reconstruction, subscription matcher, tests.

Out of scope (for now):

  • Full unescaping of \| / \$ / \\ inside a value (only \, is handled).
  • Collapsing an OR list into a single IN / = ANY(...) expression per parameter type (the planner already does BitmapOr; a per-type collapse would be a later micro-optimization).

Testing

  • Unit testsSearchQueryOrValueTest: 11/11 (comma split incl. escaped comma, other escapes preserved, edge cases).
  • Integration testsSearchOrIntegrationTest: 5/5 against a real server + PostgreSQL (Testcontainers): OR union, three-value OR, OR-vs-AND distinction, OR with a non-matching value, self link comma-joining.
  • Regression — full server unit suite 242/242 green; full FHIR integration suite 501/502 green. The single failure is the pre-existing flaky ParallelCreateIntegrationTest#testCreateDuplicateStructureDefinitionsParallelDirect (a parallel race test, ~50% on any branch, passes on develop); it is unrelated to this change, which produces byte-identical SQL for the single-value (no comma) searches that test relies on.

🤖 Generated with Claude Code

Implements the FHIR search OR join: comma separated values within a single
search parameter are combined with a logical OR, while separately repeated
parameters keep the existing logical AND semantics, per
https://www.hl7.org/fhir/search.html#combining

- SearchQuery groups the parameter instances created from one comma
  separated value; the SQL filter combines the members of a group with OR
  and the groups with AND, the in-memory (subscription) matcher does the
  same, and the search self link keeps OR values comma joined within one
  parameter
- a comma escaped as \, is treated as a literal character (and unescaped);
  other escape sequences are left for the parameter type specific parsing
- no change to the individual search parameter type implementations

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant