Skip to content

[release/10.0] Fix GO batch separator not recognized in comments and escaped identifiers#37521

Merged
AndriySvyryd merged 20 commits intorelease/10.0from
copilot/fix-go-batch-separator-issue
Feb 2, 2026
Merged

[release/10.0] Fix GO batch separator not recognized in comments and escaped identifiers#37521
AndriySvyryd merged 20 commits intorelease/10.0from
copilot/fix-go-batch-separator-issue

Conversation

Copy link
Contributor

Copilot AI commented Jan 16, 2026

Fixes #37494

Description

EF Core splits SQL Server migration scripts into batches on lines starting with GO. To avoid splitting inside string literals, SqlServerMigrationsSqlGenerator tracks whether it is inside a quoted string.

The implementation does not handle standard SQL block comments (/* ... */). If a block comment contains a single quote, the quoted state is incorrectly toggled even though the quote is inside a comment. Since there is no matching closing quote, quoted toggle remains true across subsequent lines. As a result, a later GO line is not recognized as a batch separator and is sent to SQL Server as literal text, causing:

Microsoft.Data.SqlClient.SqlException: Incorrect syntax near 'go'.

Customer impact

Customers using SQL migrations with stored procedures or other SQL scripts that include block comments containing single quotes will experience migration failures with "Incorrect syntax near 'go'" errors. This can occur when documentation comments in SQL scripts use contractions or possessives (e.g., "It's", "user's").

Workarounds:

  • Remove single quotes from block comments
  • Use two single quotes in block comments to escape them

How found

Customer reported on 10.0.1

Regression

Yes, from EF Core 9.0. Introduced in #34917.

Testing

Added 31 tests covering:

  • Block comments with single quotes (single-line and multi-line)
  • Line comments with block comment markers
  • Empty block comments
  • Block comments with line comments inside
  • Escaped identifiers with square brackets [GO] and double quotes "GO"
  • Escaped closing brackets in identifiers [g]]o]
  • Escaped double quotes in identifiers "go""lum"
  • Multi-line escaped identifiers spanning newlines with go text inside (e.g., INSERT INTO "\ngo\n" VALUES (1))
  • All character combinations (quotes, slashes, asterisks, dashes, brackets) preceding GO
  • Line comments (--) inside quotes and escaped identifiers
  • Unclosed delimiters within block comments (e.g., /* [bracket */ - valid SQL since comments don't require matched delimiters)
  • Unclosed delimiters within line comments (e.g., -- [column - valid SQL since line comments end at EOL)
  • Single quotes inside block comments
  • All delimiter types inside line comments
  • Escaped quotes in strings ('test''s value')
  • Multiple delimiters in strings

Risk

Medium, because the fix entails changes to a parser, so all the possible consequences aren't as clear. However, the changes only affect custom SQL operations in migrations.

- Add tracking for block comments (/* ... */) to prevent incorrect quote state toggling
- Block comments can now contain single quotes without affecting GO batch separator recognition
- Add comprehensive tests for various block comment scenarios
- All tests pass successfully

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix GO batch separator recognition for block comments Fix GO batch separator not recognized when block comment contains single quote Jan 16, 2026
Copilot AI requested a review from AndriySvyryd January 16, 2026 00:27
Removed separate if statements and i++ increments. Block comment detection now integrated into the main switch statement, making the code cleaner and more maintainable.

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Added test to verify that /* inside a line comment (-- /*) doesn't trigger block comment state and GO is still correctly recognized as a batch separator.

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
- Changed all GO to go in new test SQL strings (will still appear as GO in output)
- Added test for multiline block comment with go on separate line to verify go inside block comments is correctly ignored

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Refactored to use foreach instead of for loop with index by tracking blockCommentStart and blockCommentEnd flags to detect /* and */ patterns across iterations.

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Copy link
Member

@artl93 artl93 left a comment

Choose a reason for hiding this comment

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

Obviously, we want to avoid regression. The more we can add, the better, but otherwise, approved.

…upport

- Changed from foreach to for loop with look-ahead to eliminate Maybe* states
- Simplified enum from 6 states to 5: Normal, Quoted, InBlockComment, InSquareBrackets, InDoubleQuotes
- Added support for escaped identifiers: [go] and "go"
- Added support for escaped closing brackets: [g]]o]
- Changed switch statement to switch expression for cleaner code
- Removed state reset logic (no longer needed without Maybe* states)
- Added 9 comprehensive tests for escaped identifiers and character combinations
- All 26 tests pass

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Copilot AI changed the title [release/10.0] Fix GO batch separator not recognized when block comment contains single quote [release/10.0] Fix GO batch separator not recognized in comments and escaped identifiers Jan 21, 2026
Copilot AI requested a review from AndriySvyryd January 21, 2026 17:57
- Renamed ParsingState.Quoted to ParsingState.InQuotes and moved to end of enum
- Enhanced tests to include EOL before/after go and escaped characters
- Added 11 new comprehensive tests:
  - Line comments inside quotes, square brackets, and double quotes
  - Brackets and double quotes inside block comments
  - Single quotes inside block comments
  - All delimiter types inside line comments
  - Escaped quotes in strings ('test''s value')
  - Multiple delimiters in strings
- Updated existing tests with better coverage (double quote escaping, EOL placement)
- All 37 SqlOperation tests pass

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
- Changed double quote identifier test to include newlines within the identifier (double quote spans multiple lines with go inside)
- Changed square bracket test to include newlines within the identifier (bracket spans multiple lines with column inside)
- Changed block comment tests to show unclosed brackets/quotes (removed closing bracket/quote to test edge cases)
- Changed line comment tests to show unclosed brackets/quotes (line comments end at EOL, so bracket/quote is not closed)
- These changes test that the parser correctly handles:
  - Multi-line escaped identifiers with go inside
  - Unclosed delimiters in comments (which are valid SQL since comments don't need matched delimiters)

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Copilot AI requested a review from AndriySvyryd January 21, 2026 20:18
@roji roji self-requested a review January 22, 2026 12:46
Copy link
Member

@roji roji left a comment

Choose a reason for hiding this comment

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

Thanks for making the changes, this is now easier to follow and I can't think of any problems.

@AndriySvyryd AndriySvyryd added this to the 10.0.4 milestone Feb 2, 2026
@AndriySvyryd AndriySvyryd merged commit 2bea786 into release/10.0 Feb 2, 2026
7 checks passed
@AndriySvyryd AndriySvyryd deleted the copilot/fix-go-batch-separator-issue branch February 2, 2026 20:49
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.

4 participants