Skip to content

Add support for CQL 2.0 new Retrieve.codeComparators - #402

Draft
dehall wants to merge 3 commits into
masterfrom
cql2_codeComparators
Draft

dehall wants to merge 3 commits into
masterfrom
cql2_codeComparators

Conversation

@dehall

@dehall dehall commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

DRAFT because these features are not supported in the translator yet. Do not merge this until the translator is updated and we confirm these work with real ELM. In addition there are some open TODOs and questions, see below.

This PR adds support for the new Retrieve.codeComparator options introduced in CQL 2.0: ~in, contains, and ~contains. Note that because of how Retrieves work, there's not really any overlap in the implementations of these codeComparator options and the same operators as standalone operators (see #388 for those, but I can merge everything into one PR when ready, if that's preferable)

In general, these codeComparator options work the same way as the corresponding standalone operators, but in the context of a Retrieve, ~contains has some additional special meaning. https://cql.hl7.org/v2.0-changelog.html#contains-in-a-retrieve
The description there isn't as complete as I personally needed to understand the use case so here's a deeper explanation (some of this is also included in the code comments)
The example there comes from QICore, so let's look at QICore negation more broadly: https://hl7.org/fhir/us/qicore/STU7.0.2/negation.html#extent-of-negation
When something is negated, it can either be a single code that is negated, or an entire class of concepts that are negated.

  • Negation of a single code in a MedicationAdministrationNotDone is represented in medicationCodeableConcept.coding
  • Negation of a whole class in a MedicationAdministrationNotDone is medicationCodeableConcept.extension:codeOptions, whose value is a canonical(ValueSet)

So let's say we want a Retrieve for "MedicationAdministrationNotDone representing penicillin", we want to write [MedicationAdministrationNotDone: "Penicillin"] where that "Penicillin" is a single RxNorm code. We want to find both medicationCodeableConcept.coding = RxNorm 834046 AND expand(medicationCodeableConcept.extension:codeOptions) contains RxNorm 834046. The way that's going to work is with the valueSetProperty of the Retrieve: https://cql.hl7.org/04-logicalspecification.html#valuesetproperty

To fully support this use case, we also need to support the valueSetProperty of the retrieve. https://cql.hl7.org/04-logicalspecification.html#valuesetproperty
So this PR also adds support for valueSetProperty by fetching a referenced ValueSet and, if the codeComparator is ~contains, checking if that VS contains the code in question.

There are still some open questions on what to do when, eg, a referenced ValueSet is unknown and there's no configured terminology service to look it up.

Also TODO, fully populate the tests with real examples. The tests added here were created by Codex, and I think should cover the full set of cases we need to consider, but the examples need to be real, once the translator supports it.

Pull requests into cql-execution require the following.
Submitter and reviewer should ✔ when done.
For items that are not-applicable, mark "N/A" and ✔.

Submitter:

  • This pull request describes why these changes were made
  • Code diff has been done and been reviewed (it does not contain: additional white space, not applicable code changes, debug statements, etc.)
  • Tests are included and test edge cases
  • Tests have been run locally and pass
  • Code coverage has not gone down and all code touched or added is covered.
  • Code passes lint and prettier (hint: use npm run check to run tests, lint, and prettier)
  • All dependent libraries are appropriately updated or have a corresponding PR related to this change
    Reviewer:

Name:

  • Code is maintainable and reusable, reuses existing code and infrastructure where appropriate, and accomplishes the task’s purpose
  • The tests appropriately test the new code, including edge cases
  • You have tried to break the code

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.04651% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.33%. Comparing base (e87e3fa) to head (c75b7ce).

Files with missing lines Patch % Lines
src/elm/external.ts 85.71% 4 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #402      +/-   ##
==========================================
+ Coverage   89.21%   89.33%   +0.11%     
==========================================
  Files          60       60              
  Lines        5081     5110      +29     
  Branches     1451     1462      +11     
==========================================
+ Hits         4533     4565      +32     
+ Misses        317      312       -5     
- Partials      231      233       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants