Skip to content

Render scalar date day-split unions as a single inline UNION ALL CTE#5639

Closed
mikaelweave wants to merge 1 commit into
mainfrom
mikaelweave-dob-union-rewrite-design
Closed

Render scalar date day-split unions as a single inline UNION ALL CTE#5639
mikaelweave wants to merge 1 commit into
mainfrom
mikaelweave-dob-union-rewrite-design

Conversation

@mikaelweave

Copy link
Copy Markdown
Contributor

Summary

For allow-listed scalar date searches (e.g. birthdate=1980-01-01), ScalarTemporalEqualityRewriter emits a day-split UnionExpression flagged with DoNotSplitIntoSeparateCtes. Previously this either fanned out into multiple CTEs (one per branch plus an aggregating CTE) or, as a bare union, produced broken SQL. This PR renders such unions as a single CTE whose branches are combined with inline UNION ALL.

Changes

  • Detection (SearchParamTableExpressionExtensions): HasUnionAllExpression / SplitExpressions now also recognize a bare UnionExpression predicate (the actual runtime shape), not just And(union).
  • Rendering (SqlQueryGenerator): AppendNewSetOfUnionAllTableExpressions dispatches on DoNotSplitIntoSeparateCtes; flagged unions go to a new AppendInlinedUnionAllTableExpression (single CTE, inline UNION ALL) reusing the extracted AppendUnionAllBranchSelect body. The non-flagged path is unchanged.
  • Sort fix (SortRewriter): a union over the sort parameter is treated as a filter match (SortWithFilter), fixing a 500 for birthdate=...&_sort=birthdate.
  • Chain fix (SqlQueryGenerator): a date-overlap Concatenation now restricts against the same predecessor as its sibling CTE, fixing a reverse-chain case (_has:...&birthdate=...) that returned 0 rows.
  • Flag propagation through ExpressionRewriter.VisitUnion.

Tests

  • Unit coverage for bare-union detection, split decisions, and the inline single-CTE vs multi-CTE SQL shapes.
  • New/ported E2E DateSearchTests / ChainingSearchTests scenarios; fixed a generic-Task compile error in DateSearchTests.
  • All 1025 Microsoft.Health.Fhir.SqlServer.UnitTests pass on net8.0 and net9.0.

Mark day-split unions produced by ScalarTemporalEqualityRewriter so SQL expression splitting keeps them as a single union expression. Add unit coverage for union marker behavior and split decisions, and port DOB/chaining E2E scenarios from the temporal rewriter union-handling branch.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mikaelweave mikaelweave requested a review from a team as a code owner June 25, 2026 14:28
@mikaelweave

Copy link
Copy Markdown
Contributor Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (main@e75be63). Learn more about missing BASE report.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main    #5639   +/-   ##
=======================================
  Coverage        ?   76.96%           
=======================================
  Files           ?      999           
  Lines           ?    36706           
  Branches        ?     5554           
=======================================
  Hits            ?    28249           
  Misses          ?     7104           
  Partials        ?     1353           
🚀 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