Skip to content

Missing support for namespace qualified library names #1090

@baseTwo

Description

@baseTwo

Summary

The SDK fails to parse/resolve namespace-qualified library names in CQL library and include declarations. This prevents consumers from organizing libraries by namespace (e.g., MyOrg.FHIR.Measurement) and breaks interop with tooling/spec-compliant CQL that uses namespace-scoped names.

Impact

  • CQL with qualified library identifiers cannot be compiled/resolved.
  • Breaks modularization and reuse across teams/orgs.
  • Blocks adoption in environments where standards or internal guidelines require namespaces.
  • Causes runtime and/or compile-time errors in evaluation pipelines.

Examples

Problematic CQL (namespace-qualified library name):

CQL

library  "MyOrg.FHIR.Measurement"  version '1.2.3'
using  FHIR  version '4.0.1'
include  "MyOrg.FHIR.Common"  version '1.0.0' called  Common
include  "FHIRHelpers"  version '4.0.1' called  FHIRHelpers

context  Patient

define  "Adult":
   AgeInYears()  >=  18

Observed behavior:

  • Parser rejects the library identifier due to . in the name or
  • Library resolver treats the fully-qualified name as invalid/unknown and fails to locate the resource (e.g., expects simple identifiers only).

Expected behavior:

  • Parser accepts namespace-qualified library identifiers (e.g., MyOrg.FHIR.Measurement).
  • Resolver locates libraries by fully-qualified name + version (and supports mapping to physical package/file names).
  • include works with namespace-qualified libraries and aliases.

Steps to Reproduce

  1. Create a CQL file with a namespace-qualified library name and an include referencing another qualified library:

    CQL

    library  "Acme.Quality.HEDIS"  version '0.9.0'
    
    using  FHIR  version '4.0.1'
    
    include  "Acme.Common"  version '1.0.0' called  Common
    
    // ... rest of library
  2. Compile/parse the CQL via the SDK:

    C#

    // Pseudocode
    
    var  result  =  CqlCompiler.Compile("Acme.Quality.HEDIS.cql",  options);
  3. Observe failure (parse error or unresolved include).

Actual Result

  • Parser error such as: Invalid library identifier token '.' at position ...
    or
  • Resolution error such as: Library 'Acme.Quality.HEDIS' (0.9.0) not found.

Expected Result

  • Compilation succeeds; AST preserves fully-qualified identifiers.
  • Library resolution resolves Acme.Quality.HEDIS and Acme.Common by namespace + version.
  • Generated ELM includes the correct library identifiers.

Logs / Error Messages (sample)

[Parser] Unexpected token '.' after Identifier at line 1, column 15.
[Resolver] Could not resolve library 'MyOrg.FHIR.Common' version '1.0.0'.

Technical Notes / Hypothesis

  • Lexer/Parser likely restricts identifier to [A-Za-z_][A-Za-z0-9_]* and rejects dotted qualifiers.
  • Symbol Table / Resolver assumes a flat library namespace (simple names only) and does not support namespacing in keys.
  • File/URI mapping may need configuration to translate qualified library names to paths (e.g., MyOrg/FHIR/Measurement.cql or MyOrg.FHIR.Measurement.cql).
  • Version strategy should remain unchanged; only identifier parsing/matching expands.
  • Backwards compatibility: Simple identifiers must remain valid.

Proposed Fix (Outline)

  1. Grammar: Extend LibraryIdentifier to accept dot-separated segments, e.g.:

    LibraryIdentifier := Identifier ('.' Identifier)*
    
    
  2. Resolver:

    • Use fully-qualified name as the primary key in the library registry.
    • Support a pluggable name-to-resource mapping (e.g., provider callback) for custom path conventions.
  3. ELM:

    • Ensure emitted ELM preserves library.identifier.id = "MyOrg.FHIR.Measurement".
  4. Includes:

    • Normalize includes to fully-qualified form for matching; enforce version semantics unchanged.
  5. Diagnostics:

    • Improve error messages to distinguish parse vs resolution failures.
  6. Tests:

    • Unit tests for parsing qualified names (a.b, a.b.c), mixed includes, and aliasing.
    • Resolver tests for mapping rules and versioned lookup.
    • Round-trip tests: CQL → ELM → execution with qualified libraries.

Acceptance Criteria

  • ✅ CQL with namespace-qualified library identifiers parses successfully.
  • include statements with qualified names resolve when available via configured providers.
  • ✅ ELM output preserves qualified identifiers.
  • ✅ Existing CQL with simple names remains unaffected.
  • ✅ Comprehensive tests added and passing (parser, resolver, integration).
  • ✅ Documentation updated: how to configure library resolution for namespaces (file layout, package naming, nuget/zip rules, etc.).

Workarounds (Current)

  • Rename libraries to simple identifiers (undesirable, breaks namespacing).
  • Add a preprocessing step to rewrite qualified names → simple names (lossy and fragile).
  • Maintain a manual mapping in the resolver for specific libraries (not scalable).

Related / References

  • Internal: link to SDK parser grammar file, resolver component, and library provider interface.
  • Spec alignment: CQL identifier and library naming conventions (ensure we align with how tools expect qualified identifiers; note that some tools use simple names only, but organizations commonly need namespace scoping).

Attachments

  • Minimal failing CQL files (2--3 small examples).
  • Parser logs and call stack.
  • Current grammar snippet and proposed diff.
  • Unit tests demonstrating failure (before) and success (after).

Additional context**

Discussion on Zulip

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions