Skip to content

Translate byte[].Contains with a non-constant byte to a one-byte BLOB… - #39106

Merged
AndriySvyryd merged 1 commit into
dotnet:mainfrom
ilkertskn:fix/sqlite-byte-array-contains-high-byte
Oct 2, 2026
Merged

AndriySvyryd merged 1 commit into
dotnet:mainfrom
ilkertskn:fix/sqlite-byte-array-contains-high-byte

Conversation

@ilkertskn

Copy link
Copy Markdown
Contributor

… on SQLite

SqliteByteArrayMethodTranslator translated bytes.Contains(b) with a parameter or column argument to instr(bytes, char(b)). char() returns TEXT containing the UTF-8 encoding of the code point, which makes instr compare as text rather than as bytes, so every value above 0x7F was wrong in both directions: instr(X'DEADBEEF', char(222)) returns 0 (missed match), while instr(X'01C38802', char(200)) returns 2 (false match on the UTF-8 bytes of U+00C8). The constant path already built a proper BLOB literal.

Build the search value as unhex(printf('%02X', b)) instead, which yields a one-byte BLOB and makes instr compare bytes, and add a test with a byte above the ASCII range.

  • [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

… on SQLite

SqliteByteArrayMethodTranslator translated `bytes.Contains(b)` with a parameter
or column argument to `instr(bytes, char(b))`. `char()` returns TEXT containing
the UTF-8 encoding of the code point, which makes `instr` compare as text
rather than as bytes, so every value above 0x7F was wrong in both directions:
`instr(X'DEADBEEF', char(222))` returns 0 (missed match), while
`instr(X'01C38802', char(200))` returns 2 (false match on the UTF-8 bytes of
U+00C8). The constant path already built a proper BLOB literal.

Build the search value as `unhex(printf('%02X', b))` instead, which yields a
one-byte BLOB and makes `instr` compare bytes, and add a test with a byte
above the ASCII range.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The unconditional unhex() dependency breaks older SQLite binaries, and high-byte column coverage remains incomplete.

Review effort: Lite
Findings: 1 High severity

Open (1)
What changed in this PR

Fixes SQLite byte[].Contains translation for non-ASCII bytes by generating one-byte BLOB search values.

Changes:

  • Replaces char() with unhex(printf(...)).
  • Adds high-byte test coverage and provider SQL baselines.
  • Updates Cosmos translation-failure coverage.
File Summary
test/​EFCore.SqlServer.FunctionalTests/​Query/​Translations/​ByteArrayTranslationsSqlServerTest.cs Adds SQL Server coverage for the shared test.
test/​EFCore.Sqlite.FunctionalTests/​Query/​Translations/​ByteArrayTranslationsSqliteTest.cs Updates SQLite baselines and high-byte assertions.
test/​EFCore.Specification.Tests/​Query/​Translations/​ByteArrayTranslationsTestBase.cs Adds high-byte test coverage.
test/​EFCore.Cosmos.FunctionalTests/​Query/​Translations/​ByteArrayTranslationsCosmosTest.cs Marks the new test as unsupported.
src/​EFCore.Sqlite.Core/​Query/​Internal/​Translators/​SqliteByteArrayMethodTranslator.cs Generates one-byte BLOB search values.

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

@AndriySvyryd AndriySvyryd left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution!

@AndriySvyryd
AndriySvyryd merged commit 28e4af1 into dotnet:main Oct 2, 2026
20 checks passed
@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 12.0-preview1 milestone Oct 3, 2026
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.

3 participants