Repository navigation
Translate Clamp on the remaining range types, each once it agrees with memory as Int32Range, Int64Range and DecimalRange do #486
Description
Problem
Clamp(value) translates on Int32Range, Int64Range and DecimalRange (#406, 10.3.0). On every other range type it runs in memory only. docs/efcore.md#what-runs-where gives a reason about verification, not a known disagreement: "The same LEAST(GREATEST(…)) form would apply, but it has only been checked against memory on Int32Range, Int64Range and DecimalRange."
That's where #478's ten set families were before #478 measured them. Measure each remaining type, translate those that agree, and name the disagreement for those that don't.
Change
Extend the translation one type at a time, each after ClampParityTests agrees with memory on PostgreSQL 16 and 18:
Float64Range,Float32Range. Continuous. To measure: which zero comes back when the value is-0and a bound is0(memory andLEAST/GREATESTmay pick different ones), and therealcasts.DateRange,LocalDateRange. Discrete: one day back from an exclusive upper bound, as the integer types step back one. To measure: an exclusive upper bound atDateOnly.MaxValue. Npgsql writes it asinfinity, and'infinity'::date - 1is stillinfinity, while memory steps back to 9999-12-30. Measure with Npgsql's infinity conversions on and off (the InfinityDisabled integration project).YearMonthRange. Stored as a month-aligneddaterange, so the step back is a month, not a day.DateTimeRange,DateTimeOffsetRange,LocalDateTimeRange,InstantRange. Continuous. To measure: a value with sub-microsecond ticks inside the range, which memory returns as it is and the database truncates on bind, and the bounds at the extremes, which Npgsql maps to±infinity.TimeRange. To measure:timeallows24:00:00, whichTimeOnlydoesn't.
A type whose disagreement can't be handled in the SQL (for example by a CASE at the extreme) stays in memory, with the reason in what-runs-where, as Length does for temporal ranges.
Does it change an answer?
No. For each widened type, a predicate that throws today gets the in-memory answer, and a projection that clamped in memory gives the same result in SQL. A type that would answer differently is not widened. It lands on main first and is cherry-picked with -x into release/10.x as a 10.x minor.
Done when
- each widened type has its SQL asserted in
ClampTranslationTestsand its answers inClampParityTests, on PostgreSQL 16 and 18, including bounds at the extremes and, for temporal types, the InfinityDisabled project docs/efcore.md#what-runs-where: the twoClamprows say which types run where and why- the seed
clamp-reads-the-stored-exclusive-upper-boundis still caught, andShapeMatrixCoverageTestsandDiscreteDomainBoundaryTestscover the new types
Activity
Merge pull request #490 from CaffeinatedCoder/feat/486-translate-clam…
Merge pull request #498 from CaffeinatedCoder/feat/494-translate-clam…