SQL-on-FHIR Implementation
This crate provides a complete implementation of the SQL-on-FHIR specification for Rust, enabling the transformation of FHIR resources into tabular data using declarative ViewDefinitions. It supports all major FHIR versions (R4, R4B, R5, R6) through a version-agnostic abstraction layer.
Overview
The sof crate implements the HL7 FHIR SQL-on-FHIR Implementation Guide, providing:
- ViewDefinition Processing - Transform FHIR resources into tabular data using declarative configuration
- Multi-Version Support - Works seamlessly with R4, R4B, R5, and R6 FHIR specifications
- FHIRPath Integration - Complex data extraction using FHIRPath expressions
- Multiple Output Formats - CSV, JSON, NDJSON, and planned Parquet support
- Command Line Interface - Ready-to-use CLI tool for batch processing
- Server Implementation - HTTP API for on-demand transformations (planned)
Executables
This crate provides two executable targets:
sof-cli - Command Line Interface
A full-featured command-line (CLI) tool for running ViewDefinition transformations. The CLI tool accepts FHIR ViewDefinition and Bundle resources as input (either from files or stdin) and applies the SQL-on-FHIR transformation to produce structured output in formats like CSV, JSON, or other supported content types.
# Basic CSV output (includes headers by default)
# CSV output without headers
# JSON output to file
# Read ViewDefinition from stdin, Bundle from file
|
# Read Bundle from stdin, ViewDefinition from file
|
# Filter resources modified after a specific date
# Limit results to first 100 rows
# Combine filters: recent resources limited to 50 results
CLI Features
- Flexible Input: Read ViewDefinitions and Bundles from files or stdin (but not both from stdin)
- Output Formats: CSV (with/without headers), JSON (pretty-printed array), NDJSON (newline-delimited), Parquet (planned)
- Output Options: Write to stdout (default) or specified file with
-o - Result Filtering:
- Filter resources by modification time with
--since(RFC3339 format) - Limit number of results with
--limit(1-10000)
- Filter resources by modification time with
- FHIR Version Support: R4 by default; other versions (R4B, R5, R6) require compilation with feature flags
- Error Handling: Clear, actionable error messages for debugging
Command Line Options
-v, --view <VIEW> Path to ViewDefinition JSON file (or use stdin if not provided)
-b, --bundle <BUNDLE> Path to FHIR Bundle JSON file (or use stdin if not provided)
-f, --format <FORMAT> Output format (csv, json, ndjson, parquet) [default: csv]
--no-headers Exclude CSV headers (only for CSV format)
-o, --output <OUTPUT> Output file path (defaults to stdout)
--since <SINCE> Filter resources modified after this time (RFC3339 format)
--limit <LIMIT> Limit the number of results (1-10000)
--fhir-version <VERSION> FHIR version to use [default: R4]
-h, --help Print help
* Additional FHIR versions (R4B, R5, R6) available when compiled with corresponding features
Output Formats
The CLI supports multiple output formats via the -f/--format parameter:
-
csv (default) - Comma-separated values format
- Includes headers by default
- Use
--no-headersflag to exclude column headers - All values are properly quoted according to CSV standards
-
json - JSON array format
- Pretty-printed for readability
- Each row is a JSON object with column names as keys
- Suitable for further processing with JSON tools
-
ndjson - Newline-delimited JSON format
- One JSON object per line
- Streaming-friendly format
- Ideal for processing large datasets
-
parquet - Apache Parquet columnar format
- Efficient binary format (not yet implemented)
- Planned for future releases
sof-server - HTTP Server
A high-performance HTTP server providing SQL-on-FHIR ViewDefinition transformation capabilities. Use this server if you need a stateless, simple web service for SQL-on-FHIR implementations. Should you need to perform SQL-on-FHIR transformations using server-stored ViewDefinitions and server-stored FHIR data, use the full capabilities of the Helios FHIR Server in hfs.
# Start server with defaults
# Custom configuration via command line
# Custom configuration via environment variables
SOF_SERVER_PORT=3000 SOF_SERVER_HOST=0.0.0.0
# Check server health
# Get CapabilityStatement
Configuration
The server can be configured using either command-line arguments or environment variables. Command-line arguments take precedence when both are provided.
Environment Variables
| Variable | Description | Default |
|---|---|---|
SOF_SERVER_PORT |
Server port | 8080 |
SOF_SERVER_HOST |
Server host address | 127.0.0.1 |
SOF_LOG_LEVEL |
Log level (error, warn, info, debug, trace) | info |
SOF_MAX_BODY_SIZE |
Maximum request body size in bytes | 10485760 (10MB) |
SOF_REQUEST_TIMEOUT |
Request timeout in seconds | 30 |
SOF_ENABLE_CORS |
Enable CORS (true/false) | true |
SOF_CORS_ORIGINS |
Allowed CORS origins (comma-separated, * for any) | * |
SOF_CORS_METHODS |
Allowed CORS methods (comma-separated, * for any) | GET,POST,PUT,DELETE,OPTIONS |
SOF_CORS_HEADERS |
Allowed CORS headers (comma-separated, * for any) | Common headers¹ |
Command-Line Arguments
| Argument | Short | Description | Default |
|---|---|---|---|
--port |
-p |
Server port | 8080 |
--host |
-H |
Server host address | 127.0.0.1 |
--log-level |
-l |
Log level | info |
--max-body-size |
-m |
Max request body (bytes) | 10485760 |
--request-timeout |
-t |
Request timeout (seconds) | 30 |
--enable-cors |
-c |
Enable CORS | true |
--cors-origins |
Allowed origins (comma-separated) | * |
|
--cors-methods |
Allowed methods (comma-separated) | GET,POST,PUT,DELETE,OPTIONS |
|
--cors-headers |
Allowed headers (comma-separated) | Common headers¹ |
Examples
# Production configuration with environment variables
# 50MB
# Development configuration
# CORS configuration for specific frontend
# Disable CORS for internal services
# Show all configuration options
CORS Configuration
The server provides flexible CORS (Cross-Origin Resource Sharing) configuration to control which web applications can access the API:
-
Origins: Specify which domains can access the server
- Use
*to allow any origin (default) - Provide comma-separated list for specific origins:
https://app1.com,https://app2.com
- Use
-
Methods: Control which HTTP methods are allowed
- Default:
GET,POST,PUT,DELETE,OPTIONS - Use
*to allow any method - Provide comma-separated list:
GET,POST,OPTIONS
- Default:
-
Headers: Specify which headers clients can send
- Default: Common headers¹
- Use
*to allow any header - Provide comma-separated list:
Content-Type,Authorization,X-Custom-Header
Important Security Notes:
- When using wildcard (
*) for origins, credentials (cookies, auth headers) are automatically disabled for security - To enable credentials, you must specify exact origins, not wildcards
- In production, always specify exact origins rather than using
*to prevent unauthorized access
# Development (permissive, no credentials)
# Production CORS configuration (with credentials)
¹ Default headers: Accept,Accept-Language,Content-Type,Content-Language,Authorization,X-Requested-With
Server Features
- HTTP API: RESTful endpoints for ViewDefinition execution
- CapabilityStatement: Discovery endpoint for server capabilities
- ViewDefinition Runner: Synchronous execution of ViewDefinitions
- Multi-format Output: Support for CSV, JSON, and NDJSON responses
- FHIR Compliance: Proper OperationOutcome error responses
- Configurable CORS: Fine-grained control over cross-origin requests with support for specific origins, methods, and headers
API Endpoints
GET /metadata
Returns the server's CapabilityStatement describing supported operations:
POST /ViewDefinition/$run
Execute a ViewDefinition transformation:
# JSON output (default)
# CSV output (includes headers by default)
# CSV output without headers
# NDJSON output
Parameters
The $run POST operation accepts parameters either as query parameters or in a FHIR Parameters resource.
Parameter table:
| Name | Type | Use | Scope | Min | Max | Documentation |
|---|---|---|---|---|---|---|
| _format | code | in | type, instance | 1 | 1 | Output format - application/json, application/ndjson, text/csv, application/parquet |
| header | boolean | in | type, instance | 0 | 1 | This parameter only applies to text/csv requests. true (default) - return headers in the response, false - do not return headers. |
| viewReference | Reference | in | type, instance | 0 | 1 | Reference to ViewDefinition to be used for data transformation. (not yet supported) |
| viewResource | ViewDefinition | in | type | 0 | 1 | ViewDefinition to be used for data transformation. |
| patient | Reference | in | type, instance | 0 | * | Filter resources by patient. |
| group | Reference | in | type, instance | 0 | * | Filter resources by group. (not yet supported) |
| source | string | in | type, instance | 0 | 1 | If provided, the source of FHIR data to be transformed into a tabular projection. (not yet supported) |
| _limit | integer | in | type, instance | 0 | 1 | Limits the number of results. (1-10000) |
| _since | instant | in | type, instance | 0 | 1 | Return resources that have been modified after the supplied time. (RFC3339 format, validates format only) |
| resource | Resource | in | type, instance | 0 | * | Collection of FHIR resources to be transformed into a tabular projection. |
Query Parameters
All parameters except viewReference, viewResource, patient, group, and resource can be provided as POST query parameters:
- _format: Output format (required if not in Accept header)
application/json- JSON array output (default)text/csv- CSV outputapplication/ndjson- Newline-delimited JSONapplication/parquet- Parquet file
- header: Control CSV headers (only applies to CSV format)
true- Include headers (default for CSV)false- Exclude headers
- source: A String (not yet supported)
- _limit: Limit results (1-10000)
- _since: Filter by modification time (RFC3339 format)
Body Parameters
For POST requests, parameters can be provided in a FHIR Parameters resource:
- _format: As valueCode or valueString (overrides query params and Accept header)
- header: As valueBoolean (overrides query params)
- viewReference: As valueReference (not yet supported)
- viewResource: As resource (inline ViewDefinition)
- patient: As valueReference
- group: As valueReference (not yet supported)
- source: As valueString (not yet supported)
- _limit: As valueInteger
- _since: As valueInstant
- resource: As resource (can be repeated)
Parameter Precedence
When the same parameter is specified in multiple places, the precedence order is:
- Parameters in request body (highest priority)
- Query parameters
- Accept header (for format only, lowest priority)
Examples
# Limit results - first 50 records as CSV
# CSV without headers, limited to 20 results
# Using header parameter in request body (overrides query params)
# Filter by modification time (requires resources with lastUpdated metadata)
Core Features
ViewDefinition Processing
Transform FHIR resources using declarative ViewDefinitions:
use ;
// Parse ViewDefinition and Bundle
let view_definition: ViewDefinition = from_str?;
let bundle: Bundle = from_str?;
// Wrap in version-agnostic containers
let sof_view = R4;
let sof_bundle = R4;
// Transform to CSV with headers
let csv_output = run_view_definition?;
Multi-Version FHIR Support
Seamlessly work with any supported FHIR version:
// Version-agnostic processing
match fhir_version
Advanced ViewDefinition Features
forEach Iteration
Process collections with automatic row generation:
Constants and Variables
Define reusable values for complex expressions:
Where Clauses
Filter resources using FHIRPath expressions:
Union Operations
Combine multiple select statements:
Output Formats
Multiple output formats for different integration needs:
use ContentType;
// CSV without headers
let csv = run_view_definition?;
// CSV with headers
let csv_headers = run_view_definition?;
// Pretty-printed JSON array
let json = run_view_definition?;
// Newline-delimited JSON (streaming friendly)
let ndjson = run_view_definition?;
// Apache Parquet (planned)
let parquet = run_view_definition?;
Architecture
Version-Agnostic Design
The crate uses trait abstractions to provide uniform processing across FHIR versions:
// Core traits for version independence
Processing Pipeline
- Input Validation - Verify ViewDefinition structure and FHIR version compatibility
- Constant Extraction - Parse constants/variables for use in expressions
- Resource Filtering - Apply where clauses to filter input resources
- Row Generation - Process select statements with forEach support
- Output Formatting - Convert to requested format (CSV, JSON, etc.)
Error Handling
Comprehensive error types for different failure scenarios:
use SofError;
match run_view_definition
Feature Flags
Enable support for specific FHIR versions:
[]
= { = "1.0", = ["R4", "R5"] }
# Or enable all versions
= { = "1.0", = ["R4", "R4B", "R5", "R6"] }
Available features:
R4- FHIR 4.0.1 support (default)R4B- FHIR 4.3.0 supportR5- FHIR 5.0.0 supportR6- FHIR 6.0.0 support
Integration Examples
Batch Processing Pipeline
use ;
use fs;
Custom Error Handling
use ;
Testing
The crate includes comprehensive tests covering:
- ViewDefinition Validation - Structure and logic validation
- FHIRPath Integration - Expression evaluation and error handling
- Multi-Version Compatibility - Cross-version processing
- Output Format Validation - Correct CSV, JSON, and NDJSON generation
- Edge Cases - Empty results, null values, complex nested structures
- Query Parameter Validation - Pagination, filtering, and format parameters
- Error Handling - Proper FHIR OperationOutcome responses for invalid parameters
Run tests with:
# All tests
# Specific FHIR version
# Integration tests only