Clinical Query Language (CQL)
Constants can be integers, decimal numbers or strings (quoted with single or double quotes):
1
1.1
'string'
"string"
Maths operators follow normal precedence rules:
1 + 2 * 3 equates to 7
Strings can be concatenated:
'a' & 'b' equates to 'ab'
Dates, times and datetime values are quoted and indicated thus:
d'13 MAR 1967'
t'10:12:13'
dt'13 MAR 1967 10:12:13'
All valid Rave date and time formats are supported, including unknown values for partial dates:
d'UN UNK 1967'
t'09:12 PM'
Parenthesis can be used to control order of evaluation
(6-2)/((1+1)*2) equates to 1
Values can be compared:
1 < 2
1 <= 2
1 == 1
1 != 1
2 > 1
2 >= 1
Logical operators follow normal precedence rules (AND, OR, NOT)
1 < 2 OR 2 < 3
NOT 1 > 2
Data references are composed of the Folder, Form and Field OIDs, separated by the '.' character:
FOLDER_OID.FORM_OID.FIELD_OID == 1
Folder OID is optional and can be wildcarded, but Form and Fields OIDs are mandatory:
*.FORM_OID.FIELD_OID == 1
Record Positions and Folder/Form repeat numbers can be specified:
FOLDER_OID[1].FORM_OID[1].FIELD_OID[1] == 1
and can be wild-carded using '*':
FOLDER_OID[*].FORM_OID[*].FIELD_OID[*] == 1
Variable only data references are prefixed with the ':' character:
:VARIABLE == 1
:VARIABLE[1] == 1
If not specified the reference will default to 'StandardValue'. This can be changed by appending the data value type:
*.FORM.FIELD.CodedValue
*:VARIABLE.UserValue
Logical Record Position (LRP) functions must specify the scope (Form, Folder or Subject):
min(FOLDER_OID.FORM_OID.FIELD_OID in Folder)
max(FOLDER_OID.FORM_OID.FIELD_OID in Subject)
and order (RecordDate or CRFLocation):
first(FOLDER_OID.FORM_OID.FIELD_OID in Form order by RecordDate)
last(FOLDER_OID.FORM_OID.FIELD_OID in Folder order by CRFLocation)
next(FOLDER_OID.FORM_OID.FIELD_OID in Form order by RecordDate)
previous(FOLDER_OID.FORM_OID.FIELD_OID in Subject order by CRFLocation)
Data objects have methods:
FOLDER_OID.FORM_OID.FIELD_OID.IsEmpty
FOLDER_OID.FORM_OID.FIELD_OID.IsNotEmpty
FOLDER_OID.FORM_OID.FIELD_OID.InLocalLabRange
FOLDER_OID.FORM_OID.FIELD_OID.IsPresent
FOLDER_OID.FORM_OID.FIELD_OID.IsActive
FOLDER_OID.FORM_OID.FIELD_OID.IsNonConformant
The same operation can be applied to multiple data values at the same time using the 'ANY' and 'ALL' functions.
any(*.FORM.FIELD1, *.FORM.FIELD2, *.FORM.FIELD3) == 1
all(*.FORM.FIELD1, *.FORM.FIELD2, *.FORM.FIELD3).IsPresent
are equivalent to:
*.FORM.FIELD1 == 1 or *.FORM.FIELD2 == 1 or *.FORM.FIELD3 == 1
*.FORM.FIELD1.IsPresent and *.FORM.FIELD2.IsPresent and *.FORM.FIELD3.IsPresent
There are string and date functions:
FOLDER_OID.FORM_OID.FIELD_OID Contains 'abc'
FOLDER_OID.FORM_OID.FIELD_OID StartsWith 'abc'
FOLDER_OID.FORM_OID.FIELD_OID AddSec 20
FOLDER_OID.FORM_OID.FIELD_OID AddMin 10
FOLDER_OID.FORM_OID.FIELD_OID AddHour 2
FOLDER_OID.FORM_OID.FIELD_OID AddDay 1
FOLDER_OID.FORM_OID.FIELD_OID AddMonth 12
FOLDER_OID.FORM_OID.FIELD_OID AddYear 1
FOLDER_OID.FORM_OID.FIELD_OID Contains 'abc'
FOLDER_OID.FORM_OID.FIELD_OID Contains FOLDER2.FORM2.FIELD2
FOLDER_OID.FORM_OID.FIELD_OID Contains ('a' & FOLDER2.FORM2.FIELD2)
FOLDER_OID.FORM_OID.FIELD_OID AddSec 20 * 60
FOLDER_OID.FORM_OID.FIELD_OID AddMin FOLDER.FORM.FIELD
And functions to calculate the differences between date/times:
age(*.FORM.DOB, *.FORM.VSDT)
dayspan(*.FORM.VSDT1, *.FORM.VSDT2)
timespan(*.FORM.DOB, *.FORM.VSDT)
String length comparisons use a 'Length' function. The following is equivalent to the 'LengthIsGreaterThanOrEqual' Rave check function:
length( FOLDER_OID.FORM_OID.FIELD_OID ) <= 10
Everything is case-insensitive. The following are equivalent:
FOLDER_OID.FORM_OID.FIELD_OID.IsEmpty
Folder_OID.Form_OID.field_oid.isempty
FOLDER_OID.FORM_OID.FIELD_OID.ISEMPTY
Whitespace is generally ignored, except that '(' must follow immediately after function names. This is valid:
age(*.FORM.DOB, *.FORM.VSDT)
This is not valid because of the space between 'age' and '(':
age (*.FORM.DOB, *.FORM.VSDT)
Custom functions can be called using the 'customfunction' function, or 'cf' for short:
customfunction('cf_name')
cf('cf_name')
and can reference the previous step:
FOLDER_OID.FORM_OID.FIELD_OID.customfunction('cf_name')