Repository navigation
fix: read a YearMonthRange upper bound in a query as the first day of its month (#511, port of #506) - #515
Merged
CaffeinatedCoder merged 5 commits intoOct 26, 2026
Conversation
… its month (#506) A YearMonthRange is a month-aligned daterange, and a YearMonth operand binds as the first day of its month. UpperBound() read upper(x) - 1, the last day of the last month: it loaded as that month, but in a filter it compared unequal to it, and greater. UpperBound() == january and Clamp(february) == january were false for [2026-01,2026-01], where memory gives true; RangeSet.UpperBound() and Clamp read the same helper. A definition can name a CoarseUpperBound: the span of one element as an interval, and the element an inclusive infinity stands for. YearMonthRange steps back a month, CAST(upper(x) - INTERVAL '1 month' AS date), and answers 9999-12-01 when the bound is infinity, which no interval steps back from (9999-12 ends on the date Npgsql writes as infinity). With the infinity conversions disabled the bound is a finite 10000-01-01 and the interval reaches 9999-12-01 itself. ClampDomainParityTests compares Clamp(@p) with every point by ==, < and > in a filter on all thirteen range types; YearMonthBoundParityTests does the same for LowerBound() and UpperBound() of the range and its set. With the dispatch removed both fail on YearMonthRange (420 Clamp disagreements), and the other twelve types agree. Found-By: RV Defect-Class: SQL Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 2ca9c86)
…ry, with the migration and changelog (#511) Store a YearMonthRange says the query reads the first day of the end month and compares with a month in a filter as memory does, 9999-12 included; the discrete-bounds note points there; architecture.md says how (CoarseUpperBound). A section under Changed answers in 10.4.0, the Changed answers rows of 10.4.0 in the root and EF Core NodaTime changelogs linking #511, and claim E88. (cherry picked from commit cd76720, with the 10.x changelog and migration layout) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nfinity conversions off (#506) 9999-12 ends on 9999-12-31, which Npgsql then sends as a date, so the server keeps [...,10000-01-01): a month back reaches 9999-12-01 without the infinity arm. Fails with the step reverted to a day. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 989d54d) (cherry picked from commit 03bdb40f155b61bdf7f339f05702da35ccf2d661)
This was referenced Oct 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #511
Port of #509 (#506) to
release/10.x. The fix, test and seed commits are cherry-picked with-xand applied without conflicts. The docs commit is re-made for 10.x's layout.Problem
In a query, a
YearMonthRangeupper bound read as the last day of its month. It loaded as the right month, but in a filterUpperBound() == monthwasfalseand> monthwastruefor a range ending in that month.Clamp(which runs as SQL from 10.4.0) andRangeSet.UpperBound()read the same helper.Change
As #509:
CoarseUpperBound, YearMonth's("1 month", 9999-12), andCoarseUpperwritingCASE WHEN NOT isfinite(upper(x)) THEN DATE '9999-12-01' ELSE CAST(upper(x) - INTERVAL '1 month' AS date) END.### Changed answersrows in[10.4.0](root and EF Core NodaTime), linking 10.x: read a YearMonthRange upper bound in a query as the first day of its month (port of #506) #511 and#changed-answers-in-1040.YearMonthRangeupper bounds compared in queries under## Changed answers in 10.4.0.main.Tests
On
release/10.x, EF Core 10.0.0 floor:YearMonthBoundParityTests, theClampDomainParityTestscomparisons andYearMonthUpperBoundTestswith the infinity conversions off.oracles.cs seeds yearmonth-upper: both seeds caught, the day step by both oracles and the droppedinfinityarm byYearMonthBoundParityTests.-p:EfFloat=10.0.13 -p:NpgsqlEfFloat=10.0.3): the three YearMonth and Clamp classes, 30/30.ClampDomainParityTestsandYearMonthBoundParityTests, 14/14.🤖 Generated with Claude Code