Skip to content

Return NULL from DateInterval.Intersection for disjoint intervals - #4121

Open
Ahmed7991 wants to merge 1 commit into
npgsql:mainfrom
Ahmed7991:nodatime-dateinterval-intersection-null
Open

Ahmed7991 wants to merge 1 commit into
npgsql:mainfrom
Ahmed7991:nodatime-dateinterval-intersection-null

Conversation

@Ahmed7991

Copy link
Copy Markdown

Fixes #4083

NodaTime's DateInterval.Intersection returns null when the two intervals share no day, but the translation used the daterange * daterange operator, which returns empty for disjoint ranges, never NULL. Because the result was also treated as non-nullable, null tests on it were folded away: == null became WHERE FALSE and != null dropped the filter.

This translates Intersection to:

CASE
    WHEN a && b THEN a * b
END

which returns NULL when the ranges don't overlap. Because the CASE has no ELSE, EF's nullability processing now treats the result as nullable.

Tests

  • Updated the SQL baseline of the existing Intersection test.
  • Added Intersection_with_disjoint_interval_is_null and Intersection_with_disjoint_interval_not_null. Without the fix they return the wrong rows (expected 1/actual 0, and expected 0/actual 1).
  • DateIntervalTranslationsTest: 24/24 pass. All NodaTime translation tests: 243/243 pass (PostgreSQL 17 + PostGIS 3.5).

Not in this PR: DateInterval.Union has a related mismatch, noted in #4083. It needs a different fix because PostgreSQL raises an error for non-contiguous unions. #4084 tracks the general nullability issue with PostgreSQL operators. This PR only fixes Intersection.

NodaTime returns null when two intervals share no day, but PostgreSQL's
daterange * operator returns an empty range, so null tests on the result
filtered the wrong rows. Translate to CASE WHEN a && b THEN a * b END.

Fixes npgsql#4083

This branch has not been deployed

No deployments
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.

DateInterval.Intersection translates to *, so a null test on the result filters wrongly

1 participant