Skip to content

Epic: 10.3.0 #408

Closed
26 of 26 issues completed
Closed

Description

@CaffeinatedCoder

Goal

10.3.0 is the third release on the 10.x LTS line, shipped from release/10.x. It delivers the first new SQL translations as a small, proven expansion: scalar members that run in memory today and that composed SQL can answer exactly as memory does. Decided 2026-10-25 after an outside review of the translation reasons (#402). 10.2.0 (#358) stays corrective and ships first; its scope doesn't change.

Widened 2026-10-25, before work started, with what the additions already depend on: the translation-support inventory, the main fixes behind the two ports, and two small internal fixes and a docs item in the same area. No new kind of feature was added.

Prerequisites

The additions can't meet their "done when" without these, so each addition is linked as blocked by them.

In scope

Additions (in priority order)

  1. Translate Length on Int32Range and Int64Range #405: Length on Int32Range and Int64Range. Compact scalar SQL with explicit widening, plus the numeric path and NULL for Int64Range's too-large counts. Done on main (PR feat: translate Length on Int32Range and Int64Range (#405) #437), and on release/10.x as 10.x: translate Length on Int32Range and Int64Range (port of #405) #438 (PR feat: translate Length on Int32Range and Int64Range, on 10.x (port of #405, #438) #439).
  2. Translate Clamp on Int32Range, Int64Range and DecimalRange #406: Clamp on Int32Range, Int64Range and DecimalRange. LEAST/GREATEST over the existing bound semantics, with no subquery. Done on main (PR feat: translate Clamp on Int32Range, Int64Range and DecimalRange (#406) #440), and on release/10.x as 10.x: translate Clamp on Int32Range, Int64Range and DecimalRange (port of #406) #441 (PR feat: translate Clamp on Int32Range, Int64Range and DecimalRange, on 10.x (port of #406, #441) #442).
  3. Translate the calendar factories when they read a column #191: the calendar factories over a column (Month, Quarter, Year, IsoWeek). Measured on PostgreSQL 16 and 18. to_date rolls week 53 over, so it isn't used. make_date accepts the year 10000, so the year has a guard. [) over date_trunc(infinity) is empty, so the range is built from memory's first and last periods instead. The DateRange forms run as SQL. Done on main (PR feat: translate the DateRange calendar factories over a column (#191) #447), and on release/10.x as 10.x: translate the DateRange calendar factories over a column (port of #191) #448 (PR feat: translate the DateRange calendar factories over a column (10.x, port of #191) #449). The LocalDateRange and YearMonthRange forms stay in memory, because a LocalDate at -infinity and the years before 4713 BC have no PostgreSQL date.

Changed answers

Both are documented as known differences in 10.2.0 (#397). Each removes its entry. Since the widening, #360 and #385 are committed work on main for this release (both stay in milestone 11.0.0, where they ship on main), and each blocks its port. Both are done: #360 and #385 merged into main (PRs #443, #444), and both ports into release/10.x (PRs #445, #446), so both ship in 10.3.0. The section "Known differences in 10.2.0" stays as a heading that says 10.3.0 fixes both, since 10.2.0's changelog links it.

Internal (no answer changes)

Docs (docs only, no package change, so they don't add risk to the release)

All of them land on main first and are cherry-picked into release/10.x, like the additions. None holds up the tag: one that isn't finished in time moves to the next minor.

Parity: what every translation has to show

A translation moves work from memory to the server, so where it runs changes. Its answers mustn't. Each addition is checked against memory over the loaded rows on a live server, for:

  • shapes: empty, finite, unbounded on either side, and (,);
  • domain extremes: the type's minimum and maximum, and for temporal types the values that stand for infinity;
  • nullable operands: a nullable column, the optional side of an outer join, a nullable argument. Rule (c) applies: a value-producing member over NULL is NULL;
  • composition: Where, negated Where, OrderBy, inside a composed predicate, and in a final Select, which ran in memory before, so its parity is a requirement too and not a given;
  • declared nullability: matches the function's real strictness (DeclaredNullabilityTests).

On main, the composition sweeps (OuterJoinProbeTests, NullableOperandPairProbeTests, QuantifierProbeTests) and the translation-support probe (#384) cover a new member if their discovery reaches it. Check that they do, rather than assume it. release/10.x has none of the composition sweeps, so each cherry-pick carries its own live test of the list above, as #387 and #388 did in 10.2.0. It does get the translation-support probe, through #430.

It isn't done until translation-support.json classifies it server on both lines, the translation-support probe passes, and docs/efcore.md#what-runs-where moves its row. A cell that can't match memory keeps the member in memory for that type.

Sequence

  1. 10.2.0 tags (Release 10.2.0: date the changelogs, tag v10.2.0, close the 10.x-only issues, carry the sections to main #365). Done. Open 10.3.0 on release/10.x (Open 10.3.0 on release/10.x #426). Done.
  2. Translation-support inventory: every public query member classified as server, client-only or planned, and probed against EF Core #384 merges into main (PR test: translation-support inventory — every public query member classified and probed against EF Core (#384) #386), then 10.x: translation-support inventory, every public query member classified and probed (port of #384) #430 ports it. Sweep the EF translators for name-only dispatch and default operand classification #295 and main: RangeSetContains.Equivalent hands any other one-argument Contains on RangeSet to the value overload #320 land on main around the same time, and 10.x: RangeSetContains.Equivalent hands any other one-argument Contains to the value overload (port of #320) #326 follows. Done 2026-10-25 (10.x: map each translator operand from its declared type, and sweep for it (port of #295) #433 ported Sweep the EF translators for name-only dispatch and default operand classification #295).
  3. Each addition merges into main first, so the 11 line has it before 10.x does (CONTRIBUTING.md#branches-and-releases). Then it's cherry-picked with -x into a PR against release/10.x. The same goes for Value set Union is declared NULL only for a NULL operand, but array_cat isn't strict: a filter and a projection disagree on a NULL column #360 and RangeLowerBoundComparer.Compare runs as SQL in the range order: EF Core rewrites any Compare(a, b) to the natural comparison #385, through 10.x: value set Union and Remove over a NULL operand project a value instead of NULL (port of #360) #395 and 10.x: RangeLowerBoundComparer.Compare in a query runs in the range order (port of #385) #396.
  4. Tag. Done 2026-10-25: v10.3.0 on 2230e73, all four packages on nuget.org (Release 10.3.0: date the changelogs, tag v10.3.0, carry the sections to main #470). The carry to main is chore: carry the 10.3.0 sections to main (#470) #474, and 10.4.0 is opened in chore: open 10.4.0 on release/10.x (#473) #475 (epic Epic: 10.4.0 #472).

Not in scope

Release

Tag v10.3.0 on release/10.x. The root changelog section has ### Added for #405, #406 and #191, and ### Changed answers for #395 and #396 (both rows are in, linking docs/migration.md#changed-answers-in-1030). When 10.3.0 is carried back to main, add ## Changed answers in 10.3.0 to main's docs/migration.md (the rows link blob/main/docs/migration.md#changed-answers-in-1030), pointing at the two sections under Migration from v10.x, and say there that the last two of its list also shipped in 10.3.0.

Activity

  1. added this to the 10.3.0 milestone on Oct 25, 2026
  2. added
    epicTracks a release or a theme; its sub-issues are the work
    area/releaseVersioning, changelogs, release wiring
    on Oct 25, 2026
  3. 10 remaining items

  4. CaffeinatedCoder commented on Oct 25, 2026

    @CaffeinatedCoder
    OwnerAuthor

    State, 2026-10-25: #405 (Length) and #406 (Clamp) run as SQL on both lines (ports #438 and #441). Open: #191 (calendar factories over a column, measurements first) and #56 (docs). Still blocked by their main fixes: #395 (needs #360) and #396 (needs #385).

  5. CaffeinatedCoder commented on Oct 25, 2026

    @CaffeinatedCoder
    OwnerAuthor

    State, 2026-10-25: every remaining item has a PR on both lines. #452 (silent, from the pre-release sweep): #453 → main, #454 → release/10.x. #450: #455 / #458. #451: #456 / #459, each stacked on #450's PR. #56: #457 / #460. Merge order: #453 and #454 first, since #452 is the only one that changes an answer; then #455 before #456 and #458 before #459. Each issue is closed by hand once its 10.x PR merges. The seed prover from the pre-release review was still running when these were opened.

  6. CaffeinatedCoder commented on Oct 25, 2026

    @CaffeinatedCoder
    OwnerAuthor

    State, 2026-10-25 21:09 UTC: every sub-issue is closed. Merged on both lines, in order: #452 (#453, #454), #450 (#455, #458), #451 (#456, #459) and #56 (#457, #460). Each 10.x issue was closed by hand after its 10.x PR merged. #461 pinned CI's .NET 10 SDK to 10.0.402 (#462 on release/10.x, #463 on main): Microsoft's aka.ms link for "latest 10.0" redirects to a host answering 409. GitHub's own submit-nuget dependency submission still fails on that download; the pin can't reach it, and it isn't a required check. Left for the tag: the dates in the five changelog headings, and the seed prover result from the pre-release review session. release.yml first runs with the pin at v10.3.0.

  7. CaffeinatedCoder commented on Oct 25, 2026

    @CaffeinatedCoder
    OwnerAuthor

    10.3.0 shipped on 2026-10-25. The v10.3.0 tag is on 2230e73, release run 40236600453 is green, all four packages are on nuget.org, and the GitHub release is Latest. The run was also the first use of the 10.0.402 SDK pin in release.yml (#461), which held.

    What shipped

    Pre-tag checks

    After the tag

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/releaseVersioning, changelogs, release wiringepicTracks a release or a theme; its sub-issues are the work

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions