Using CQL with FHIR, published by HL7 International / Clinical Decision Support. This guide is not an authorized publication; it is the continuous build for version 2.0.0-ballot built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/HL7/cql-ig/ and changes regularly. See the Directory of published versions
This topic specifies conformance requirements for systems that support authoring, publishing, distribution, and implementation of FHIR Knowledge Artifacts that make use of Clinical Quality Language (CQL).
In addition to the use of CQL directly in expression-valued elements, CQL content used within knowledge artifacts can be included through the use of a Library resource. These libraries can then be referenced from FHIR resources such as PlanDefinition and Measure using the library
element (as well as the cqf-library
extension for resources that do not declare a library
element). The content of the CQL library is included using the content
element of the Library.
Conformance Requirement 4.1 (Library Resources):
For distribution to environments that support ELM execution directly, FHIR Library resources MAY include ELM content in XML or JSON format. See the Using ELM topic for conformance requirements related to the use of ELM for distribution and implementation of CQL logic.
Conformance Requirement 4.2 (Library Name and URL):
<CQL namespace url>/Library/<CQL library name>
<CQL library name>
, SHALL be 64 characters or less, and SHOULD be 30 characters or less<CQL library version>
<CQLLibraryName>-<version>.cql
The prohibition against underscores in CQL library names is required to ensure compliance with the canonical URL pattern (because URLs by convention should not use underscores). In addition, many publishing environments will use the canonical tail (i.e. the name of the library) as the logical id of the Library resource, which does not allow underscores per the FHIR specification.
Conformance Requirement 4.3 (FHIR Type Mapping):
CQL System Type | FHIR Type |
---|---|
System.Boolean |
FHIR.boolean |
System.Integer |
FHIR.integer |
System.Decimal |
FHIR.decimal |
System.Date |
FHIR.date |
System.DateTime |
FHIR.dateTime , with the exception that seconds must be provided |
System.Long |
FHIR.string in R4, FHIR.integer64 in R5 and above |
System.Time |
FHIR.time , with the exception that seconds must be provided |
System.String |
FHIR.string |
System.Quantity |
FHIR.Quantity |
System.Ratio |
FHIR.Ratio |
System.Any |
FHIR.Any |
System.Code |
FHIR.Coding |
System.Concept |
FHIR.CodeableConcept |
Interval<System.Date> |
FHIR.Period |
Interval<System.DateTime> |
FHIR.Period |
Interval<System.Quantity> |
FHIR.Range |
For example, the following CQL expression results in a List<FHIR.Observation>
:
define "FHIRObservationListExample":
[Observation]
In the Library resource, this is represented as a parameter
:
{
"extension": [{
"url": "http://hl7.org/fhir/StructureDefinition/cqf-cqlType",
"valueString": "List<FHIR.Observation>"
}],
"name": "FHIRObservationListExample",
"use": "out",
"min": 0,
"max": "*",
"type": "Observation"
}
Note the parameter is multi-cardinality to indicate this is a list-valued expression. Also note the use of the cqf-cqlType
extension to relay the CQL type.
When invoked through an operation (such as $cql
or Library/$evaluate
), this would be represented as multiple entries in the resulting Parameters resource:
{
"name": "FHIRObservationListExample",
"resource": {
"resourceType": "Observation",
"id": "blood-glucose",
"status": "final",
...
}
}, {
"name": "FHIRObservationListExample",
"resource": {
"resourceType": "Observation",
"id": "blood-pressure",
"status": "final",
...
}
}, {
"name": "FHIRObservationListExample",
"resource": {
"resourceType": "Observation",
"id": "bmi",
"status": "final",
...
}
}
Note that for an empty list, the cqf-isEmptyList
extension is used:
{
"extension": [{
"url": "http://hl7.org/fhir/StructureDefinition/cqf-cqlType",
"valueString": "List<FHIR.Observation>"
}],
"name": "FHIRObservationEmptyListExample",
"_valueBoolean": {
"extension": [{
"url": "http://hl7.org/fhir/StructureDefinition/cqf-isEmptyList",
"valueBoolean": true
}]
}
}
Note that the extension is provided on the value
element, and an arbitrary choice of boolean
is selected; there is no value to provide, the result is an empty list, so this is just a way to provide the cqf-isEmptyList extension (because parameters in a FHIR Parameters resource must have a value element).
For the special case of nested lists, where a parameter name is not available, the name element
SHALL be used. For example:
define CQLListListExample:
{ { 1, 2, 3 }, { 4, 5, 6 } }
The result of this expression is represented in the resulting Parameters resource as:
{
"extension": [{
"url": "http://hl7.org/fhir/StructureDefinition/cqf-cqlType",
"valueString": "List<List<System.Integer>>"
}],
"name": "CQLListListExample",
"part": [{
"name": "element",
"valueInteger": 1
}, {
"name": "element",
"valueInteger": 2
}, {
"name": "element",
"valueInteger": 3
}]
}, {
"extension": [{
"url": "http://hl7.org/fhir/StructureDefinition/cqf-cqlType",
"valueString": "List<List<System.Integer>>"
}],
"name": "CQLListListExample",
"part": [{
"name": "element",
"valueInteger": 4
}, {
"name": "element",
"valueInteger": 5
}, {
"name": "element",
"valueInteger": 6
}]
}
For a complete example illustrating all possible type mappings, refer to the Type Mapping Example and Type Mapping Evaluation Result Example
Conformance Requirement 4.4 (Parameters and Data Requirements):
parameter
that has parts corresponding to the elements of the tuple type. List types are represented in FHIR as a parameter
that has a cardinality of 0..*.parameter
element to identify input parameters as well as the type of all top-level expressions as output parameters.dataRequirement
element to identify any retrieves present in the CQL, according to the following mapping:Retrieve Element | DataRequirement Element |
---|---|
dataType | type |
templateId | profile |
context | subject |
codeProperty | codeFilter.path or codeFilter.searchParam |
codes (Concept) | codeFilter.code (for each Code present in the Concept) |
codes (Code) | codeFilter.code |
codes (ValueSetRef) | codeFilter.valueSet (as specified by the id of the ValueSetDef referenced by the ValueSetRef) |
dateProperty | dateFilter.path |
dateLowProperty,dateHighProperty | dateFilter.path (resolved to an interval-valued property) |
dateRange | dateFilter.path or dateFilter.searchParam |
For example, given the following CQL:
define Conditions: [Condition]
The corresponding data requirement is:
{
"type": "Condition",
"profile": [ "http://hl7.org/fhir/StructureDefinition/Condition" ]
}
When the retrieve includes a terminology filter, the codeFilter
element is used to communicate the filter:
valueset "Inpatient Encounters": 'http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113883.3.117.1.7.1.292'
...
define Encounters: [Encounter: "Inpatient Encounters"]
{
"type": "Encounter",
"codeFilter": [ {
"path": "type",
"valueSet": "http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113883.3.117.1.7.1.292"
} ]
}
The cqf-isSelective
extension MAY be used to identify selective data requirements (i.e. data requirements that are likely to be the most selective of the data of interest for the artifact:
{
"extension": [ {
"url": "http://hl7.org/fhir/StructureDefinition/cqf-isSelective",
"valueBoolean": true
} ],
"type": "Encounter",
"codeFilter": [ {
"path": "type",
"valueSet": "http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113883.3.117.1.7.1.292"
} ]
}
Although this extension may be used by artifact authors as a way to indicate expected selectivity of a data requirement, it will more typically be used by implementers and downstream packaging repositories to indicate selectivity of a data requirement given known data heuristics in particular datasets.
The cqf-fhirQueryPattern
extension MAY be used to recommend a FHIR RESTful query that can be used to satisfy the data requirement:
{
"extension": [ {
"url": "http://hl7.org/fhir/StructureDefinition/cqf-fhirQueryPattern",
"valueString": "Encounter?subject=Patient/&type:in=http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113883.3.117.1.7.1.292"
} ],
"type": "Encounter",
"profile": [ "http://hl7.org/fhir/us/qicore/StructureDefinition/qicore-encounter" ],
"codeFilter": [ {
"path": "type",
"valueSet": "http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113883.3.117.1.7.1.292"
} ]
}
Systems that can infer more selective requirements from additional restrictions applied in the CQL after the retrieve MAY include those requirements to provide more selective data requirements. For example:
define "Completed Inpatient Encounters":
[Encounter: "Inpatient Encounters"] E
where E.status = 'finished'
The status
restriction is represented using the cqf-valueFilter
extension:
{
"extension": [ {
"extension" : [
{
"url" : "path",
"valueString" : "status"
},
{
"url" : "comparator",
"valueCode" : "eq"
},
{
"url" : "value",
"valueString" : "finished"
}
],
"url" : "http://hl7.org/fhir/StructureDefinition/cqf-valueFilter"
} ],
"type": "Encounter",
"codeFilter": [ {
"path": "type",
"valueSet": "http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113883.3.117.1.7.1.292"
} ]
}
Elements that are referred to in the CQL MAY be communicated using the mustSupport
element:
define "Inpatient Encounters During Measurement Period":
[Encounter: "Inpatient Encounters"] E
where E.period during "Measurement Period"
{
"type": "Encounter",
"mustSupport": [ "period" ],
"codeFilter": [ {
"path": "type",
"valueSet": "http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113883.3.117.1.7.1.292"
} ]
}
When using profile-informed authoring, the retrieve will have a templateId
corresponding to the profile:
{
"type": "Encounter",
"profile": [ "http://hl7.org/fhir/us/qicore/StructureDefinition/qicore-encounter" ],
"codeFilter": [ {
"path": "type",
"valueSet": "http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113883.3.117.1.7.1.292"
} ]
}
When referencing extensions that are surfaced as elements in profile-informed authoring, the mustSupport
uses the .extension()
function in FHIRPath, and the rendered-value
extension is used to provide a human-readable rendering, corresponding to the sliceName
of the extension:
using QICore
...
define SDEEthnicity: Patient.ethnicity
{
"type": "Patient",
"profile": [ "http://hl7.org/fhir/us/qicore/StructureDefinition/qicore-patient" ],
"mustSupport": [ "extension('http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity')" ],
"_mustSupport": [
{
"extension": [{
"url": "http://hl7.org/fhir/StructureDefinition/rendered-value",
"valueString": "ethnicity"
}]
}
]
}
In the case that dynamic CQL construction is required, implementers should take care to sanitize inputs from any parameters used in the construction of dynamic CQL to avoid injection attacks.
Conformance Requirement 4.5 (Related Artifacts):
relatedArtifact
element to identify includes, code systems, value sets, and data models used by the CQL library:Dependency | RelatedArtifact representation |
Data Model (using declaration) | depends-on with url of the ModelInfo Library (e.g. http://hl7.org/fhir/Library/FHIR-ModelInfo|4.0.1 ) |
Library (include declaration) | depends-on with url of the Library (e.g. http://hl7.org/fhir/Library/FHIRHelpers|4.0.1 ) |
Code System | depends-on with url of the CodeSystem (e.g. http://loing.org ) |
Value Set | depends-on with url of the ValueSet (e.g. http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113762.1.4.1116.89 ) |
Conformance Requirement 4.6 (Specifying CQL Version):
For example, the following media types indicate version 1.5 of the CQL specification.
text/cql; version=1.5
application/elm+xml; version=1.5
application/elm+json; version=1.5
CQL can be used in expression-valued elements in the following ways:
To distinguish these use cases, the language
element of the expression value is used as specified in the Using Expressions topic of the FHIR specification.
The "primary library" for an artifact is determined as follows:
library
element (e.g. PlanDefinition.library), and there is one and only one library specified, that is the primary librarycqf-library
extension, that is the primary libraryIf there is more than one library specified in the resource, then expression identifiers must be qualified with the name of the library (see Conformance Requirement 2.3 (Nested Libraries)).
Certain elements in the profiles defined in this implementation guide are marked as Must Support. This flag is used to indicate that the element plays a critical role in defining, sharing, and implementing artifacts, and implementations SHALL understand and process the element.
In addition, because artifact specifications typically make use of data implementation guides (e.g. International Patient Summary(IPS), US Core, QI-Core), the implications of the Must Support flag for profiles used from those implementation guides must be considered.
For more information, see the definition of Must Support in the base FHIR specification.
Conformance Requirement 4.7 (Must Support Elements):
For resource instances claiming to conform to profiles from this IG, Must Support on any profile data element SHALL be interpreted as follows: