Skip to content

Don't fold a filtered subquery into a join whose key is an equality b… - #39103

Open
ilkertskn wants to merge 1 commit into
dotnet:mainfrom
ilkertskn:fix/sqlite-subquery-join-fold-null-keys
Open

ilkertskn wants to merge 1 commit into
dotnet:mainfrom
ilkertskn:fix/sqlite-subquery-join-fold-null-keys

Conversation

@ilkertskn

Copy link
Copy Markdown
Contributor

…etween nullable expressions on SQLite

SqliteSubqueryToJoinRewriter (#38692) rewrites JOIN (SELECT ... WHERE filter) ON key into JOIN table ON key AND filter. It runs at compile time, before SqlNullabilityProcessor, which deliberately leaves a join predicate consisting of a single top-level equality uncompensated because LINQ equijoins don't match null with null. After the fold the equality is nested under an AND, so it gets the regular a = b OR (a IS NULL AND b IS NULL) compensation and NULL keys start matching each other, returning extra rows compared to LINQ (and to SQL Server, which doesn't fold).

Skip the fold when the join key is a single equality whose two sides can both be null; when at least one side is non-nullable no compensation is generated anyway, so those joins keep being flattened. Adds inner and left join tests with a filtered inner source to NullSemanticsQueryTestBase.

  • [x ] I've read the guidelines for contributing and seen the walkthrough
  • [x ] I've posted a comment on an issue with a detailed description of how I am planning to contribute and got approval from a member of the team
  • [x ] The code builds and tests pass locally (also verified by our automated build checks)
  • [x ] Commit messages follow this format:
        Summary of the changes
        - Detail 1
        - Detail 2

        Fixes #bugnumber
  • [x ] Tests for the changes have been added (for bug fixes / features)
  • [x ] Code follows the same patterns and style as existing code in this repo

…etween nullable expressions on SQLite

SqliteSubqueryToJoinRewriter (dotnet#38692) rewrites `JOIN (SELECT ... WHERE filter) ON key`
into `JOIN table ON key AND filter`. It runs at compile time, before
SqlNullabilityProcessor, which deliberately leaves a join predicate consisting of a
single top-level equality uncompensated because LINQ equijoins don't match null with
null. After the fold the equality is nested under an AND, so it gets the regular
`a = b OR (a IS NULL AND b IS NULL)` compensation and NULL keys start matching each
other, returning extra rows compared to LINQ (and to SQL Server, which doesn't fold).

Skip the fold when the join key is a single equality whose two sides can both be
null; when at least one side is non-nullable no compensation is generated anyway, so
those joins keep being flattened. Adds inner and left join tests with a filtered
inner source to NullSemanticsQueryTestBase.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant