12. Paths and query
Requirement prefix: Q12.
openEHR paths#
- Q12.1 The crate MUST parse openEHR paths of the form
/attribute[predicate]/attribute…, with predicates in these forms:[at0004],[openEHR-EHR-OBSERVATION.x.v2],['Systolic'],[at0004, 'Systolic'],[archetype_node_id='at0004'],[name/value='Systolic'],[2], and conjunctions withandor,. - Q12.2 A parse failure MUST report the offset at which parsing stopped.
- Q12.3 Quoted digits MUST be a name, not an index:
['3']is an element named3. - Q12.4 Index predicates are zero-based. openEHR's own examples are inconsistent and implementations differ; this crate documents zero-based and means it, because every other index in it is zero-based and one crate with two conventions produces off-by-one errors that read as correct code.
- Q12.5
path_exists,path_unique,items_at_path, anditem_at_pathMUST all be available, anditem_at_pathMUST fail on an ambiguous path rather than returning the first match. Taking the first of three repeatedELEMENTs silently returns one of three diagnoses. - Q12.6 A path naming an attribute the node's class does not have MUST resolve to no match rather than to a parse error: the path is well formed and this instance does not have it.
- Q12.7 Navigation MUST cover the composition tree from
COMPOSITIONdown to primitive attributes of aDATA_VALUE, includingvalue/magnitude,value/units,value/value, anddefining_code. - Q12.7a Navigation MUST reach the
DV_ORDEREDattributes —normal_range,other_reference_ranges,normal_status— and MUST continue through aDV_INTERVALtolower,upper, the two*_unboundedflags and the two*_includedflags, and through aREFERENCE_RANGEtomeaningandrange. A reference range is queried in practice — "results outside their own normal range" is a population query a clinician actually asks — and a path that stops at the value cannot express it. - Q12.7b The
*_unboundedflags MUST be navigable even though they are derived rather than stored (base::interval). Whether the answer is looked up or computed is not something a path should have to know. - Q12.8 A parsed path MUST print in the long predicate form and MUST re-parse to an equal path.
AQL#
- Q12.9 The crate MUST parse
SELECT(withDISTINCTandTOP), aliases, function calls,FROMwithCONTAINS/NOT CONTAINS/AND/ORand parentheses, archetype and standard predicates,WHEREwith the comparison operators andAND/OR/NOT/EXISTS/MATCHES/LIKE,$parameters,ORDER BYwithASC/DESC, andLIMIT/OFFSET. - Q12.9a Constructs the crate does not model —
SELECT *, theVERSIONclass extension, terminology-function subqueries — MUST be refused with an error naming this requirement, never parsed-and-ignored. A partially-understood query that looks fully understood is the failure mode. - Q12.10 The crate MUST NOT execute AQL (
S1.5), and no API may return anything shaped like a result set. - Q12.11 Keywords MUST be case-insensitive.
- Q12.12 A parse failure MUST report a byte offset.
- Q12.13 The archetype ids, aliases, and parameters a query touches MUST be enumerable before it runs. That is what an authorisation check needs.
- Q12.14 A static check MUST report a path rooted at an alias that
FROMdoes not bind. This is the error AQL's syntax makes easiest to write — rename a class alias and miss oneSELECTcolumn — and hardest to see, because such a query is syntactically perfect and returns nothing. - Q12.15 A parsed query MUST render to text that re-parses to an equivalent query.