Skip to content

Translate string.Trim with characters to TRIM on SQL Server - #39603

Open
officialasishkumar wants to merge 1 commit into
dotnet:mainfrom
officialasishkumar:feature/22927-sqlserver-trim-characters
Open

officialasishkumar wants to merge 1 commit into
dotnet:mainfrom
officialasishkumar:feature/22927-sqlserver-trim-characters

Conversation

@officialasishkumar

Copy link
Copy Markdown
Contributor

Fixes #22927

On SQL Server, string.Trim() without arguments translates to LTRIM(RTRIM(...)), and TrimStart/TrimEnd with characters translate to the SQL Server 2022 LTRIM/RTRIM overloads. Trim with characters wasn't translated at all, so a query like Where(b => b.Name.Trim('-') == "foo") failed with a translation error.

Fix

Trim(char) and Trim(char[]) now translate to TRIM with its characters FROM syntax:

WHERE TRIM(N'Se' FROM [b].[String]) = N'attl'
  • TRIM is available from SQL Server 2017, so the translation applies when the compatibility level is 140 or higher (and on Azure SQL with 140 or higher, and on Azure Synapse), the same way string.Join → CONCAT_WS is gated. With older compatibility levels the query fails translation as before.
  • The translator creates a regular built-in TRIM function with the string and the characters as its arguments, and SqlServerQuerySqlGenerator writes it as TRIM(characters FROM string). This follows the existing special cases there (ISNULL, JSON_OBJECT, modify), so no new expression type is needed, and nullability, parameter extraction and precompiled queries work as for any other function.
  • The characters argument is handled as for TrimStart/TrimEnd, so I shared that code (ProcessTrimStartEnd is renamed to ProcessTrim): a constant char or char[] is inlined as a string literal, and a char parameter is sent as a one-character string. A non-constant char[] still isn't translated.
  • Trim() without characters is unchanged (LTRIM(RTRIM(...))).

Tests

  • StringTranslationsSqlServerTest: Trim_with_char_argument_in_predicate and Trim_with_char_array_argument_in_predicate previously asserted a translation failure that referenced this issue. They now assert the TRIM SQL when IsFunctions2017Supported, and a translation failure otherwise, like the TrimStart/TrimEnd tests do for 2022.
  • StringTranslationsTestBase: new Trim_with_char_parameter_in_predicate, Trim_with_non_ASCII_char_parameter_in_predicate and Trim_with_char_array_parameter_in_predicate, matching the existing TrimStart/TrimEnd tests, with overrides for SQL Server, SQLite and Cosmos.

I ran StringTranslationsSqlServerTest (122 passed) against Azure SQL Edge (SQL Server 2019 engine, below compatibility level 160), so the new TRIM assertions ran against a real server, with the data assertions checking the trimmed results, while the TrimStart/TrimEnd character tests took their translation-failure branch. I also ran StringTranslationsSqliteTest (125 passed) and StringTranslationsInMemoryTest (115 passed), and built the Cosmos test project. I only ran these test classes, not the full suite.

  • I've read the guidelines for contributing and seen the walkthrough
  • 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
  • The code builds and tests pass locally (also verified by our automated build checks)
  • Commit messages follow this format:
        Summary of the changes
        - Detail 1
        - Detail 2

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

- Translate string.Trim(char) and string.Trim(char[]) to TRIM(characters FROM string) when targeting SQL Server 2017 (compatibility level 140) or later, Azure SQL or Azure Synapse. Older targets keep failing translation as before, and Trim() without characters still translates to LTRIM(RTRIM(...)).
- Generate the TRIM(characters FROM string) syntax in SqlServerQuerySqlGenerator for a built-in TRIM function with two arguments, as is already done for the special syntax of other functions.
- Share the character handling of TrimStart/TrimEnd (constant char and char[], char parameters sent as a one-character string), and rename ProcessTrimStartEnd to ProcessTrim accordingly.
- Add Trim tests with a char parameter, a non-ASCII char parameter and a char array parameter, matching the existing TrimStart/TrimEnd tests, and update the SQL Server baselines.

Fixes dotnet#22927
@officialasishkumar
officialasishkumar requested a review from a team as a code owner November 11, 2026 16:07
Copilot AI balanced review requested due to automatic review settings November 11, 2026 16:07

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 was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

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.

Implement string.Trim with parameters on SQL Server

2 participants