Skip to content

Implement %rowIndex environment variable#12

Merged
johngrimes merged 7 commits into
mainfrom
issue/11
Jun 19, 2026
Merged

Implement %rowIndex environment variable#12
johngrimes merged 7 commits into
mainfrom
issue/11

Conversation

@johngrimes

Copy link
Copy Markdown
Member

Implements the %rowIndex environment variable from the SQL on FHIR v2 spec, which holds the 0-based index of the current element within the collection being iterated by forEach, forEachOrNull, or repeat. This lets columns capture position for ordering or surrogate keys.

The nine %rowIndex tests in sqlonfhir/tests/row_index.json (pulled in by the submodule bump in #9) were previously failing against the MSSQL implementation and are now passing.

Spec reference: https://build.fhir.org/ig/FHIR/sql-on-fhir-v2/functional-model.html#the-foreach-and-foreachornull-functions

Work was planned and tracked via an OpenSpec change, now archived.

Fixes #11

Scaffolds the implement-row-index change with proposal, spec, design,
and tasks for resolving the SQL on FHIR %rowIndex environment variable
to a 0-based T-SQL integer across forEach, forEachOrNull, repeat, and
unionAll, so the nine in-scope row_index tests can pass.

Re #11
Recognise the SQL on FHIR %rowIndex environment variable in column path
expressions and resolve it to the 0-based position of the current element
within the active iteration.

The visitor special-cases the reserved name before the user-constant
lookup, returning a per-iteration index expression supplied via a new
TranspilerContext.rowIndexExpr field, or 0 at the resource root. forEach
and forEachOrNull set it from the OPENJSON [key] column (with a COALESCE
so the null-padded forEachOrNull row reports 0). repeat sets it to a
ROW_NUMBER window ordered by a zero-padded __order accumulator added to
the recursive CTE, giving the depth-first pre-order position. unionAll
needs no change as branches inherit or override the expression through
the shared context.

This makes the nine in-scope row_index.json conformance tests pass.

Fixes #11
Sync the row-index-variable capability into the main specs and move the
completed change to the archive.
@johngrimes johngrimes marked this pull request as ready for review May 28, 2026 19:12
@johngrimes johngrimes requested a review from piotrszul May 28, 2026 19:12
@johngrimes johngrimes moved this from Backlog to In progress in Pathling May 28, 2026
@github-project-automation github-project-automation Bot moved this to Backlog in Pathling May 28, 2026
Apply cleanup findings to the %rowIndex transpilation code:
- Extract shared qualifiedKeyCols() helper, removing the duplicated
  partition-key column mapping in repeat.ts and cteTemplates.ts.
- Collapse the orderSegment pad width into a single ORDER_SEGMENT_WIDTH
  constant so the zero-pad string and CAST width cannot drift.
- Replace inline NVARCHAR(MAX)/NVARCHAR(4000) literals with the existing
  SQL_NVARCHAR_MAX/SQL_NVARCHAR_4000 constants.
- Document that __order is emitted unconditionally per repeat CTE.

Generated T-SQL is unchanged; all in-scope compliance tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@piotrszul piotrszul left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: %rowIndex environment variable — Approve ✅

Reviewed the feature plus the follow-up Simplify %rowIndex CTE templates commit. Verified against a live SQL Server 2017-compatible instance.

Strengths

  • Clean single-channel design: TranspilerContext.rowIndexExpr carries the per-iteration expression; the visitor resolves %rowIndex to it (or 0 at the resource root), reserved before the user-constant lookup so it can't be shadowed.
  • forEachOrNull empty-collection row correctly resolves to 0 via COALESCE.
  • The lexical-sort trap in repeat is avoided via a zero-padded __order accumulator; pad width and CAST width now collapsed into a single ORDER_SEGMENT_WIDTH constant so they can't drift.
  • Simplification (qualifiedKeyCols helper, SQL_NVARCHAR_* constants) is byte-for-byte behavior-preserving.

Verification

  • Conformance suite: 133 passed / 11 failed, all 9 row_index tests green. The 11 failures are all #experimental (fn_boundary/fn_join) and out of scope per Constitution Principle I.
  • build, lint, format:check all clean. Generated T-SQL is valid for SQL Server 2017+.

Minor (non-blocking)

  • No single test exercises repeat nested inside forEach with %rowIndex — the partition-reset behavior (design Decision 3) is covered only indirectly. Optional to add.

Verdict: Spec-faithful, minimal, all in-scope tests verified green. Ready to merge.

@johngrimes johngrimes merged commit 54c74b3 into main Jun 19, 2026
3 checks passed
@johngrimes johngrimes deleted the issue/11 branch June 19, 2026 01:01
@github-project-automation github-project-automation Bot moved this from In progress to Done in Pathling Jun 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Implement %rowIndex environment variable

2 participants