Skip to content

fix(persistence): chained search honors comparator prefixes, type-guarded - #619

Open
angela-helios wants to merge 1 commit into
mainfrom
fix/258-chained-comparator
Open

fix(persistence): chained search honors comparator prefixes, type-guarded#619
angela-helios wants to merge 1 commit into
mainfrom
fix/258-chained-comparator

Conversation

@angela-helios

Copy link
Copy Markdown
Contributor

Closes #258.

The silent-empty from the issue, plus its mirror image found on the way:

  • SQLite forced SearchValue::eq onto the raw chained value, so patient.birthdate=le1956-07-14 compared dates against the literal string le1956-07-14 — zero rows, no error. gt1900-01-01 returning nothing was exactly this.
  • Postgres had the inverse bug: unconditional SearchValue::parse, so a chained string value starting with a valid prefix pair — family=Levine — lost its head to le + vine.

Both call sites now strip the prefix only when the parsed chain's terminal parameter type admits one (number/date/quantity via SearchPrefix::is_valid_for) — the same rule direct search applies. The terminal SQL arms (build_date_condition/build_number_condition) already honored value.prefix; only the call sites were wrong, so the fix is two guarded parses.

Test drives resolve_chain through the issue's repro (le includes, gt1900 matches everyone, le on an earlier date excludes) and the Levine-stays-whole guard. Full -p helios-persistence --features sqlite suite green (792), clippy clean on both backends. The ES/Mongo chain paths ride different code (registry-driven, no raw-eq call site) — the multi-backend verification pass tracked in #519 is the natural place to sweep them with the same repro.

…rded

A chained search with a comparator prefix silently returned zero rows on
SQLite: resolve_chain forced an Eq prefix onto the raw value, so
patient.birthdate=le1956-07-14 compared dates against the literal string
'le1956-07-14'. Postgres had the inverse bug: it parsed the prefix
unconditionally, so a chained string value beginning with a valid prefix
pair — family=Levine — lost its head to le + 'vine'.

Both sides now strip the prefix only when the parsed chain's terminal
parameter type admits one (number/date/quantity, via
SearchPrefix::is_valid_for), which is exactly how direct search behaves.
The terminal SQL arms already honored value.prefix; only the call sites
were wrong.

Covered by a test driving resolve_chain through le/gt dates (the
issue's repro, including gt1900 matching everyone) and the
Levine-stays-whole string guard.

Closes #258
@codecov

codecov Bot commented Aug 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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.

Chained search with a comparator prefix silently returns zero results (SQLite)

2 participants