octofhir/sof
A Rust toolkit for SQL on FHIR v2:
parse ViewDefinition resources and turn FHIR data into flat tables — with no
database required, or by generating PostgreSQL.
Documentation: https://octofhir.github.io/sof
- Two interchangeable execution paths, both passing the full official
content-test suite (144/144):
- a database-free in-memory evaluator over
serde_json, and - a PostgreSQL generator that lowers FHIRPath to SQL over JSONB.
- a database-free in-memory evaluator over
- Writers: CSV, NDJSON, JSON, and Parquet (feature-gated).
- Offline lint & validation of ViewDefinitions (FH01–FH10) with rustc-style diagnostics, plus JSON and SARIF output for CI.
- Full support for the v2.1 additions: the
repeatdirective and the%rowIndexenvironment variable, on both paths.
Install
# Prebuilt binary (detects your platform, verifies SHA-256):
|
# From crates.io:
# …or from a clone of this repo:
# …or build and run in place:
Prebuilt binaries for macOS, Linux and Windows are attached to each GitHub release.
Usage
# Run a view over FHIR files, no database — CSV to stdout
# Stream a large NDJSON export with bounded memory (NDJSON in, NDJSON out)
|
# Run every view in a directory in one pass, one output file per view
# Generate SQL for the view (PostgreSQL JSONB by default, or DuckDB JSON)
# Generate a CREATE TABLE for the view's columns (ansi | postgres | duckdb)
# Run against PostgreSQL instead of files
# Validate a ViewDefinition offline (no FHIR package needed)
# Lint selectors and generated SQL against a FHIR package (any version)
# Check a view against the portable ShareableViewDefinition FHIRPath subset
# (offline, no package). --allow-fn exempts a registered custom function.
# Run the official content-test format in memory
Exit codes: 0 on success, 1 on validation errors, lint errors, test
failures, or I/O errors.
Library
use ;
let view = parse?;
// In-memory:
let result = execute?;
// Or generate SQL:
let sql = new.generate?.sql;
For bounded-memory streaming, compile once and run resource-at-a-time:
use CompiledView;
let compiled = compile?;
for resource in resources
SQL dialects
generate emits a PostgreSQL JSONB query by default and a DuckDB JSON query
with --dialect duckdb; both come from one dialect-parametrized generator and
pass the full content-test suite (DuckDB verified through the duckdb CLI). The
in-memory engine (run --input, execute) needs no database at all.
FHIR versions
Execution is version-agnostic: the engine navigates the resource JSON and is
not coupled to any StructureDefinition, so the same view runs unchanged over R4,
R4B, R5 or R6 resources (the suite includes an R5 CodeableReference case). The
schema-driven lint (lint --package) accepts any package the canonical manager
can resolve — pass the package name and --version, e.g. hl7.fhir.r4.core,
hl7.fhir.r4b.core, hl7.fhir.r5.core, or an R6 build — there is no hard-coded
version.
Conformance
The official reference tests from
FHIR/sql-on-fhir.js are vendored under
crates/octofhir-sof/tests/spec/ (refresh with just update-spec-tests). Both
execution paths pass the full v2.1 suite (144/144). Run them:
See CONFORMANCE.md for the result-file format and how to submit our entry to the implementation registry.
License
MIT OR Apache-2.0.