You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Translate Length on Int32Range and Int64Range #405
Length on Int32Range and Int64Range runs in memory only (docs/efcore.md#what-runs-where), so a query can't filter or order by it. The obstacle the docs gave until #402 (that int4range overflows before a cast can widen it) doesn't hold: casting first works.
Change
Translate Length on both types to a scalar the server evaluates, matching memory exactly:
Int32Range (long?): CASE WHEN isempty(x) THEN 0 ELSE upper(x)::bigint - lower(x)::bigint END. An unbounded side gives NULL because upper/lower do, which is memory's null. Measured on PostgreSQL 16: 4294967295 for [-2147483648,2147483647), 0 for empty, NULL for [1,). PostgreSQL's canonical [) form makes upper - lower the count memory returns ([1,10] measures 10).
Int64Range (long?): memory computes in decimal and returns null when the count exceeds long.MaxValue. The SQL has to do the same: numeric arithmetic, and NULL above 9223372036854775807, never an int8 overflow error or a wrapped value.
Declared nullability: NULL for a NULL range too (rule (c), a value-producing member over NULL).
Done when
Every condition on the 10.3.0 epic's parity list holds for both types: empty and unbounded shapes, the domain extremes, a nullable column and an outer-join operand, Where, OrderBy, a final Select (which ran in memory before) and a composed predicate (Length > n with &&/!), each against memory over the loaded rows on a live server. translation-support.json (#384) classifies both server, and the docs move the row to "Runs as SQL". main first, then the cherry-pick to release/10.x.
PR #437 on main. Measured on PostgreSQL 16 before writing it, over columns, parameters and inlined constants:
int4range: [-2147483648,2147483646] gives 4294967295. The empty range gives 0, an unbounded side NULL, and a NULL range NULL.
int8range: [0, long.MaxValue - 1] and [long.MinValue, -2] give long.MaxValue. One more, as in [-1, long.MaxValue - 1], gives NULL, and constants too large to count raise no planning error.
The composition sweeps run over the DateRange family only, so they don't reach these members. IntegerLengthParityTests covers #408's parity list for them instead. The 10.x cherry-pick follows the merge.
Activity
CaffeinatedCoder commentedon Oct 25, 2026
PR #437 on
main. Measured on PostgreSQL 16 before writing it, over columns, parameters and inlined constants:int4range:[-2147483648,2147483646]gives 4294967295. The empty range gives 0, an unbounded side NULL, and a NULL range NULL.int8range:[0, long.MaxValue - 1]and[long.MinValue, -2]givelong.MaxValue. One more, as in[-1, long.MaxValue - 1], gives NULL, and constants too large to count raise no planning error.The composition sweeps run over the
DateRangefamily only, so they don't reach these members.IntegerLengthParityTestscovers #408's parity list for them instead. The 10.x cherry-pick follows the merge.Merge pull request #437 from CaffeinatedCoder/feat/405-translate-inte…
CaffeinatedCoder commentedon Oct 25, 2026
Runs as SQL on
mainsince PR #437 (67628e2). Therelease/10.xcherry-pick is tracked separately (port issue under #408).Merge pull request #439 from CaffeinatedCoder/feat/438-translate-inte…