SQL on FHIR WG Meetings

The FHIRPath subset has holes — starting with tests that don't obey the subset they test — May 27, 2025

Adam Culbertson
Adam Culbertson
Senior Director Emerging Technology at b.well Connected Health
John Grimes
John Grimes
Principal Research Consultant CSIRO
Arjun Sanyal
Arjun Sanyal
Principal Antidote Solutions
Nikolai Ryzhikov
Nikolai Ryzhikov
CTO at Health Samurai
Steve Munini
Steve Munini
CEO and CTO, Helios Software
May 27, 2025

The tests don't stick to the subset

The shareable profile says the FHIRPath subset covers string, integer and decimal literals — but the tests don't stick to it, and some use date literals. Nobody noticed because implementations lean on engines like fhirpath.js that handle dates anyway.

The subset also says you must implement literals and then goes quiet on whether the Boolean, maths and comparison operators have to work over those types, or over anything that isn't a literal — and some tests wander into exactly that territory.

Nikolai — write it down as typed operators

Functions are the easy half — you either support one or you don't. Operators need types.

His suggestion: name them in the spec as typed operators — string plus, decimal plus, dateTime plus — with the first two mandatory and the awkward ones optional.

Left open: macros like where, and how deeply you can nest them, since recursive grammars are hard for some implementers.

A cut-down ANTLR grammar — talked down

Since the FHIRPath spec ships one and declares it the source of truth when the prose disagrees. Talked down fairly quickly: the functions aren't in the grammar, behaviour isn't either, and it becomes one more thing to maintain.

Better idea: reference spec features from the tests, so you can see which feature each test actually depends on, and the set can grow without becoming vague.

Column types — a semantic hole

The shareable profile makes you declare a column type as a FHIR type, but a FHIRPath expression doesn't always have one — a FHIRPath string is just a string, not a FHIR string or uri or oid — and the spec has no mapping between the two.

The related question is defaults: with no hint at all, should a dateTime come out as a native type from one runner and a string from another?

The evidence for caring came from the paper

Running the same ViewDefinition on Aidbox and Pathling, the SQL wouldn't run over both results without casting — the only interoperability gap left.

The leaning was towards ANSI SQL types, because databases already document how they map to ANSI, and Parquet already carries them.

John's line: articulate the problem first. Tags already exist, are barely implemented, and the spec says almost nothing about what they mean.

Merging $run and $evaluate

Nikolai proposed merging them into one operation, on the grounds that the response is identical and the only difference is whether you send the view definition or point at one.

John offered the closest precedent — ValueSet/$expand, which takes either a url or a valueSet — so the parameter was renamed url.

$run stays single-view because it streams synchronously; $export takes a collection. A live check confirmed Parameters can't hold contained resources, which killed the other option.