Skip to content

feat(mssqlserver): support GO batch separator in init scripts - #11960

Open
klouds27 wants to merge 1 commit into
testcontainers:mainfrom
klouds27:feat/11231-mssql-go-batch-separator
Open

feat(mssqlserver): support GO batch separator in init scripts#11960
klouds27 wants to merge 1 commit into
testcontainers:mainfrom
klouds27:feat/11231-mssql-go-batch-separator

Conversation

@klouds27

@klouds27 klouds27 commented Aug 5, 2026

Copy link
Copy Markdown

Closes #11231

Scripts exported from sqlcmd or SSMS use GO as a batch separator, which is not valid SQL and causes init script execution to fail. This change makes MSSQLServerContainer handle those scripts transparently.

ScriptUtils.normalizeGoSeparator() replaces standalone GO lines with ; using a regex that matches GO case-insensitively on its own line. The regex guards against false matches on identifiers like GOOD or GOTO_COL.

A preprocessInitScript hook is added to JdbcDatabaseContainer as a protected method returning the script unchanged by default. MSSQLServerContainer overrides it to call normalizeGoSeparator. Both the current and the deprecated legacy container class are updated.

Four unit tests cover basic replacement, case insensitivity, leading whitespace, and the inline identifier guard.

…ntainers#11231)

adds ScriptUtils.normalizeGoSeparator() which replaces standalone GO
lines with ; using a regex that matches GO case-insensitively on its own
line, guarding against false matches on identifiers like GOOD or GOTO.

introduces a preprocessInitScript hook on JdbcDatabaseContainer so
subclasses can transform script content before execution. the default
implementation is a no-op. MSSQLServerContainer (both the current and
the deprecated legacy class) override it to call normalizeGoSeparator,
enabling scripts exported from sqlcmd or SSMS to work without manual
editing.

Signed-off-by: klouds27 <adalwolf@gmail.com>
@klouds27
klouds27 marked this pull request as ready for review August 6, 2026 19:04
Copilot AI lite review requested due to automatic review settings August 6, 2026 19:04
@klouds27
klouds27 requested a review from a team as a code owner August 6, 2026 19:04

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds an init-script preprocessing hook to the JDBC container flow and uses it to support MSSQL GO batch separators by normalizing them before execution.

Changes:

  • Introduce JdbcDatabaseContainer#preprocessInitScript and wire it into init script execution.
  • Add ScriptUtils.normalizeGoSeparator(...) plus a new runInitScript(...) overload that accepts a script preprocessor.
  • Override preprocessing in both MSSQLServerContainer variants to normalize GO, and add unit tests for normalization.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
modules/mssqlserver/src/main/java/org/testcontainers/mssqlserver/MSSQLServerContainer.java Override init script preprocessing to normalize MSSQL GO separators.
modules/mssqlserver/src/main/java/org/testcontainers/containers/MSSQLServerContainer.java Same override in the alternate package container implementation.
modules/jdbc/src/main/java/org/testcontainers/containers/JdbcDatabaseContainer.java Add preprocess hook and pass it into init script execution.
modules/database-commons/src/main/java/org/testcontainers/ext/ScriptUtils.java Add GO normalization and a preprocessor-aware runInitScript overload.
modules/database-commons/src/test/java/org/testcontainers/ext/ScriptSplittingTest.java Add tests validating GO normalization behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

*/
public static final String GO_STATEMENT_SEPARATOR = "GO";

private static final Pattern GO_SEPARATOR_PATTERN = Pattern.compile("(?im)^[ \\t]*GO[ \\t]*$");
Comment on lines +212 to +214
public static String normalizeGoSeparator(String script) {
return GO_SEPARATOR_PATTERN.matcher(script).replaceAll(";");
}
Comment on lines +482 to +488
@Test
void testNormalizeGoSeparatorBasic() {
String script = "SELECT 1\nGO\nSELECT 2\nGO\n";
String normalized = ScriptUtils.normalizeGoSeparator(script);
List<String> statements = doSplit(normalized, ScriptUtils.DEFAULT_STATEMENT_SEPARATOR);
assertThat(statements).containsExactly("SELECT 1", "SELECT 2");
}
Comment on lines +223 to +249
public static void runInitScript(
DatabaseDelegate databaseDelegate,
String initScriptPath,
UnaryOperator<String> scriptPreprocessor
) {
try {
URL resource = Thread.currentThread().getContextClassLoader().getResource(initScriptPath);
if (resource == null) {
resource = ScriptUtils.class.getClassLoader().getResource(initScriptPath);
if (resource == null) {
LOGGER.warn("Could not load classpath init script: {}", initScriptPath);
throw new ScriptLoadException(
"Could not load classpath init script: " + initScriptPath + ". Resource not found."
);
}
}
String scripts = IOUtils.toString(resource, StandardCharsets.UTF_8);
scripts = scriptPreprocessor.apply(scripts);
executeDatabaseScript(databaseDelegate, initScriptPath, scripts);
} catch (IOException e) {
LOGGER.warn("Could not load classpath init script: {}", initScriptPath);
throw new ScriptLoadException("Could not load classpath init script: " + initScriptPath, e);
} catch (ScriptException e) {
LOGGER.error("Error while executing init script: {}", initScriptPath, e);
throw new UncategorizedScriptException("Error while executing init script: " + initScriptPath, e);
}
}
Comment on lines +74 to +79
/**
* T-SQL batch separator used by Microsoft SQL Server tooling such as {@code sqlcmd} and SSMS.
* Pass this as the {@code separator} argument when executing scripts that use {@code GO} as a batch
* delimiter instead of {@code ;}.
*/
public static final String GO_STATEMENT_SEPARATOR = "GO";
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.

[Enhancement]: Support the default GO batch separator for MSSQL

2 participants