Clinical Quality Language Specification
2.0.0-ballot - R2 STU 1 (Ballot)

Clinical Quality Language Specification, published by Clinical Decision Support WG. 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/ and changes regularly. See the Directory of published versions

## Appendix I - FHIRPath Translation

Page standards status: Normative | Maturity Level: N

This appendix provides detailed mappings for each FHIRPath function in terms of the ELM output produced.

In addition to the function mappings below, the $index accessor can be used within the FHIRPath iteration functions (i.e. FHIRPath functions that take an expression as an argument) to access the 0-based index of the current iteration.

### .aggregate()

    X.aggregate(<iteration>, <init>) === Aggregate(<iteration>, <init>)

In addition, the $total accumulator can be used within the iteration and init expressions to access the current value of the accumulator.

### .abs()

    X.abs() === Abs(X)

### .all()

    X.all(<condition>) === AllTrue(X $this let a: <condition> where a return a)

### .allFalse()

    X.allFalse() === AllTrue(X A return not A)

### .allTrue()

    X.allTrue() === AllTrue(X)

### .anyFalse()

    X.anyFalse() === AnyTrue(X A return not A)

### .anyTrue()

    X.anyTrue() === AnyTrue(X)

### .as()

    X.as(T) === X as T

Note that the type argument T is expected to be a literal string and must resolve to the name of a type.

### .ceiling()

    X.ceiling() === Ceiling(X)

### .children()

    .children(X) === Children(X)

### .combine()

    X.combine(Y) === Flatten(\{ X, Y })

### .conformsTo()

    X.conformsTo(Y) === FHIRSupport.ConformsTo(Y)

Note that this mapping relies on an external library, FHIRSupport to provide conformance validation checking.

### .contains()

    X.contains(Y) === PositionOf(Y, X) >= 0

### .convertsToBoolean()

    X.convertsToBoolean() === ConvertsToBoolean(X)

### .convertsToDate()

    X.convertsToDate() === ConvertsToDate(X)

### .convertsToDateTime()

    X.convertsToDateTime() === ConvertsToDateTime(X)

### .convertsToDecimal()

    X.convertsToDecimal() === ConvertsToDecimal(X)

### .convertsToInteger()

    X.convertsToInteger() === ConvertsToInteger(X)

### .convertsToQuantity()

    X.convertsToQuantity() === ConvertsToQuantity(X)

### .convertsToTime()

    X.convertsToTime() === ConvertsToTime(X)

### .count()

    X.count() === Count(X)

### .dateOf()

    X.dateOf() === date from X

### .dayOf()

    X.dayOf() === day from X

### .decode()

    X.decode(format) === Decode(X, format)

### .defineVariable()

Because the defineVariable function is introducing a named alias, all subsequent fluent function invocations must be evaluated within the query.

In addition, the name argument must be compile-time evaluable.

    X.defineVariable(name) === { input: X } alias let name: alias.X return X
    X.defineVariable(name, expression) === X alias let name: expression

### .descendants()

    .descendants(X) === Descendants(X)

### .distinct()

    X.distinct() === distinct X

### .empty()

    X.empty() === not exists X

### .encode()

    X.encode(format) === Encode(X, format)

### .endsWith()

    X.endsWith(Y) === EndsWith(X, Y)

### .escape()

    X.escape(target) === Escape(X, target)

### .exclude()

    X.exclude(Y) === X except Y

### .exists()

    X.exists() === exists X

    X.exists(<condition>) === exists (X $this where <condition>)

### .exp()

    X.exp() === Exp(X)

### .first()

    X.first() === First(X)

### .floor()

    X.floor() === Floor(X)

### .hasValue()

    X.hasValue() === X is not null

### .highBoundary()

    X.highBoundary(precision) === HighBoundary(X, precision)

### .hourOf()

    X.hourOf() === hour from X

### .iif()

    iif(X, Y) === if X then Y else null

    iif(X, Y, Z) === if X then Y else Z

### .indexOf()

    X.indexOf(Y) === PositionOf(Y, X) // Note carefully the order of arguments here, it’s the opposite of IndexOf

### .intersect()

    X.intersect(Y) === X intersect Y

### .is()

    X.is(T) === X is T

Note that the argument T is expected to be a literal string and must resolve to the name of a type.

### .isDistinct()

    X.isDistinct() === Count(X) = Count(distinct X)

### .join()

    X.join(separator) === Combine(X, separator)

### .last()

    X.last() === Last(X)

### .lastIndexOf()

    X.lastIndexOf(Y) === LastPositionOf(Y, X) // Note carefully the order of arguments here, it’s the opposite of lastIndexOf.

### .length()

    X.length() === Length(X)

### .ln()

    X.ln() === Ln(X)

### .log()

    X.log(B) === Log(X, B)

### .lowBoundary()

    X.lowBoundary(precision) === LowBoundary(X, precision)

### .lower()

    X.lower() === Lower(X)

### .matches()

    X.matches(Y) === Matches(X, Y)

### .matchesFull()

    X.matchesFull(Y) === Matches(X, '^' + Y + '$')

### .memberOf()

    X.memberOf(Y) === InValueSet(X, Y) // where Y is required to be a ValueSetRef

### .millisecondOf()

    X.millisecondOf() === millisecond from X

### .minuteOf()

    X.minuteOf() === minute from X

### .monthOf()

    X.monthOf() === month from X

### .ofType()

    X.ofType(T) === X $this where $this is T return $this as T

Note that the argument T is required to be a literal string, and is interpreted as the name of a type. For non-named-types, type specifier syntax applies.

### .not()

    X.not() === not X

### .now()

    now() === Now()

### .power()

    X.power(Y) === Power(X, Y)

### .precision()

    X.precision() === Precision(X)

### .repeat()

    X.repeat(<element>) === Repeat(X, <element>)

The type of X.repeat() is inferred as the type of:

    X.select(<element>).select(<element>)

### .replace()

    X.replace(Y, Z) === Replace(X, Y, Z)

### .replaceMatches()

    X.replaceMatches(Y, Z) === ReplaceMatches(X, Y, Z)

### .round()

    X.round() === Round(X)
    X.round(Y) === Round(X, Y)

### .secondOf()

    X.secondOf() === second from X

### .select()

If the result type of is not list-valued:

    X.select(<element>) === X $this let a: <element> where a is not null return a

If the result type of is list-valued:

    X.select(<element>) === Flatten(X $this let a: <element> where a is not null return a)

### .single()

    X.single() === singleton from X

### .skip()

    X.skip(Y) === Slice(X, Y, null)

### .split()

    X.split(separator) === Split(X, separator)

### .sqrt()

    X.sqrt() === Power(X, 0.5)

### .startsWith()

    X.startsWith(Y) === StartsWith(X, Y)

### .subsetOf()

    X.subsetOf(Y) === X included in Y

### .substring()

    X.substring(Y) === SubString(X, Y)

    X.substring(Y, Z) === SubString(X, Y, Z)

### .subsumes()

    X.subsumes(Y) === Subsumes(X, Y)

### .subsumedBy()

    X.subsumedBy(Y) === SubsumedBy(X, Y)

### .supersetOf()

    X.supersetOf(Y) === X includes Y

### .tail()

    X.tail() === Slice(X, 1, null)

### .take()

    X.take(Y) === Slice(X, 0, Coalesce(Y, 0))

### .timeOf()

    X.timeOf() === time from X

### .timeOfDay()

    timeOfDay() === TimeOfDay()

### .timezoneOffsetOf()

    X.timezoneOffsetOf() === timezoneoffset from X

### .toBoolean()

    X.toBoolean() === ToBoolean(X)

### .toChars()

    X.toChars() === ToChars(X)

### .toDate()

    X.toDate() === ToDate(X)

### .toDateTime()

    X.toDateTime() === ToDateTime(X)

### .today()

    today() === Today()

### .toDecimal()

    X.toDecimal() === ToDecimal(X)

### .toInteger()

    X.toInteger() === ToInteger(X)

### .toQuantity()

    X.toQuantity() === ToQuantity(X)

### .toString()

    X.toString() === ToString(X)

### .toTime()

    X.toTime() === ToTime(X)

### .trace()

    X.trace(Y) === Message(X, true, Y, 'Trace', ToString(X)))

### .trim()

    X.trim() === Trim(X)

### .truncate()

    X.truncate() === Truncate(X)

### .unescape()

    X.unescape(target) === Unescape(X, target)

### .union() and |

    X.union(Y) === X union Y
    X | Y === X union Y

### .upper()

    X.upper() === Upper(X)

### .where()

    X.where(<condition>) === X $this where <condition>

### .yearOf()

    X.yearOf() === year from X