SQL on FHIR WG Meetings

'Why make a client fetch the result just to find out the job failed?' — Nov 4, 2025

Arjun Sanyal
Arjun Sanyal
Principal Antidote Solutions
Nikolai Ryzhikov
Nikolai Ryzhikov
CTO at Health Samurai
John Grimes
John Grimes
Principal Research Consultant CSIRO
Steve Munini
Steve Munini
CEO and CTO, Helios Software
Eugene Vestel
Eugene Vestel
Founder at HealthClaw.io
Nov 4, 2025

The motivation

Two async patterns today — the legacy bulk export, and one documented in the spec that essentially nobody uses — and the documented one insists you respond with a Bundle, which doesn't suit a read that ought to return a resource, or an operation that ought to return Parameters.

The goal: a generic pattern so any operation can be turned async, perhaps flagged in the OperationDefinition.

Nikolai Ryzhikov
Nikolai Ryzhikov
CTO at Health Samurai

The one thing we definitely don't want is to produce a fifth pattern.

The disagreement — one extra request

In Josh's draft, polling always answers 200 with a location; if the job failed, you only discover that after you fetch the result location. The justification: it lets you tell a polling error apart from a job error.

Nikolai isn't convinced the extra round trip earns that.

John Grimes
John Grimes
Principal Research Consultant CSIRO

If I already knew the job had failed, why send them fishing — I'd say so in the status.

Steve noted bulk data export hands back a bundle with a collection of successes and a collection of failures, and that sometimes it's simply nice to be told everything is fine rather than sift a big bundle to find out.

John also corrected a piece of the record: the claim that only one implementer uses the spec's existing async pattern isn't right — his side implemented it as a reusable piece and then offered it on everything, so this lands on top of something already in production.

Naming parameters in a SQL query — no standard answer

  • JDBC uses positional question marks
  • Oracle-ish style uses :name
  • C# world uses @name
  • Some use {0}/{1}, both of which force you to keep the ordering straight

Colon is awkward because SQL constructs contain colons, so Nikolai floated handlebars as safest.

John Grimes
John Grimes
Principal Research Consultant CSIRO

You need a parser regardless, because whatever symbol you pick can also appear inside a string literal.

On table names specifically, John argued they must be distinguishable from ordinary parameters because you treat them differently — you go looking for them as a table.

Arjun questioned why the table name needs to be dynamic at all; Nikolai's reason: in most systems it isn't the real table name anyway, and might be another schema or a URL in a bucket.

Two problems with repeat

  • The FHIRPath expression in the spec is simply wrong — repeat returns a collection of strings and the count counts all of it, so it breaks as soon as there are two. exists or anyTrue were floated as the fix
  • Implementers got repeat working via a common table expression — runs in Postgres, slowly. Nikolai wants to try Postgres JSON path with its recursive wildcard instead, which won't port but would prove the optimisation is there

John's open worry: whether any engine the group cares about lacks CTEs.

On Gene's CQL-to-SQL converter

Nikolai's advice: split it into pieces and bank the valuable part first — reusing the clinical reasoning infrastructure to calculate measures over ViewDefinitions and queries, without any translation at all, is already interesting on its own.

Nikolai Ryzhikov
Nikolai Ryzhikov
CTO at Health Samurai

The translation itself is a great adventure. I've watched people translate to C for years and they're still mid-journey. I tried it twice — never got it automated, and by hand always ended up writing something more efficient.

Which leaves the real question: how you prove the SQL means the same thing as the CQL. His answer: test datasets with expected results, so it stops mattering whether a human or a machine did the translating.

John's human-in-the-loop angle: what hooks does the tool give an author to review and feed back, so it augments rather than replaces?