SQL on FHIR WG Meetings





SQL on FHIR WG Meeting — July 15, 2025
Nikolai Ryzhikov
CTO at Health Samurai
Arjun Sanyal
Principal Antidote Solutions
John Grimes
Principal Research Consultant CSIRO
Steve Munini
CEO and CTO, Helios Software
Bashir Sadjad
Software Engineer at Google
Ivan Bagrov
Senior Software Engineer at Health Samurai
Jul 15, 2025
Topics discussed:
- Ivan Bagrov demoed $run working in Aidbox — view by reference, view definition in the body, resources passed inline, group and patient filters, _since and limit, JSON out for now. It took about four days to build, which Nikolai Ryzhikov offered to the other engines as motivation: spend four days and you have the API. Paging is on the to-do list and is about to be deleted from it.
- John Grimes' problem: you can run one view definition on several runners and get output you can't query, because each runner quietly picked its own column types. There is a way to hint ANSI SQL types, but nothing requires it and there's no default, so implementations have all mapped independently — which you can see in the test runners, where everyone has to be tolerant of almost anything in the expectations because the reference implementation's choices are the only de facto answer. His fix is a default: what hint is assumed when no hint is given.
- Arjun Sanyal pushed back on how useful a default can be given how differently SQL implementations treat types — decimal is a problem, strict ANSI makes you pick a size for a VARCHAR — and worried the model might be more work for implementers than the alternative. John's answer was that anyone who already supports type hinting has done this work; the only question is what's assumed in the absence of a hint. He'd defaulted nearly everything to the FHIR string form, on the argument that a good default shouldn't be lossy, and only integers, booleans and binary are genuinely safe.
- Nikolai fought for instant mapping to an ANSI timestamp, arguing that if you call it a string people will cast it to a timestamp anyway, and every query the group ever distributes will carry that cast. One decent time type also unlocks the rest: lowBoundary and highBoundary plus toInstant turns a dateTime into two properly typed instants. Bashir Sadjad reframed it as a choice of goal — losslessness gives you one list of types, reducing casts gives you another, and if every implementation already models something a given way in practice, a slightly imprecise default may beat a pure one. John conceded the point: "you've made a good argument."
- Along the way the group agreed FHIR dateTime is a range, not a point, so it can't honestly map to a SQL date, and the spec should say how to handle that rather than leave everyone to rediscover it. Hints can't be binding anyway, since not everything has a concrete ANSI mapping — and requiring a hint on every column was rejected as the cure being worse. The plan: publish as a recommendation, let other implementers beat it up, tighten later. John took the pull request, reckoning it's a table in the type hints section plus words.
- Smaller things settled: GET only works for views the server already knows, because with no body you can't send a view definition or resources; Accept carries MIME types while _format takes the short codes, as in FHIR; and a partitioned export reports multiple location values under one output name.