提交 cc0ae3a8 编写于 作者: S Sam Brannen

Support EOF as statement separator in SQL scripts

Prior to Spring Framework 4.0.3, it was possible to supply a bogus
statement separator (i.e., a separator string that does not exist in
the configured SQL scripts) to ResourceDatabasePopulator with the side
effect that the entire contents of a script file would be interpreted
as a single SQL statement.

This undocumented feature was never intentional; however, some
developers came to rely on it. Unfortunately, changes made in
conjunction with SPR-9531 and SPR-11560 caused such scenarios to no
longer work.

This commit introduces first-class support for executing scripts which
contain a single statement that spans multiple lines but is not
followed by an explicit statement separator.

Specifically, ScriptUtils.EOF_STATEMENT_SEPARATOR may now be specified
as a 'virtual' statement separator to denote that a script contains a
single statement and no actual separator.

Issue: SPR-11687
上级 2a937a36
......@@ -21,6 +21,7 @@ import javax.sql.DataSource;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.jdbc.datasource.init.ScriptUtils;
import org.springframework.util.Assert;
/**
......@@ -161,7 +162,9 @@ public class EmbeddedDatabaseBuilder {
/**
* Specify the statement separator used in all SQL scripts, if a custom one.
* <p>Default is ";".
* <p>Defaults to {@code ";"} if not specified and falls back to {@code "\n"}
* as a last resort; may be set to {@link ScriptUtils#EOF_STATEMENT_SEPARATOR}
* to signal that each script contains a single statement without a separator.
* @param separator the statement separator
* @return {@code this}, to facilitate method chaining
* @since 4.0.3
......@@ -173,7 +176,7 @@ public class EmbeddedDatabaseBuilder {
/**
* Specify the single-line comment prefix used in all SQL scripts.
* <p>Default is "--".
* <p>Defaults to {@code "--"}.
* @param commentPrefix the prefix for single-line comments
* @return {@code this}, to facilitate method chaining
* @since 4.0.3
......@@ -185,7 +188,7 @@ public class EmbeddedDatabaseBuilder {
/**
* Specify the start delimiter for block comments in all SQL scripts.
* <p>Default is "/*".
* <p>Defaults to {@code "/*"}.
* @param blockCommentStartDelimiter the start delimiter for block comments
* @return {@code this}, to facilitate method chaining
* @since 4.0.3
......@@ -198,7 +201,7 @@ public class EmbeddedDatabaseBuilder {
/**
* Specify the end delimiter for block comments in all SQL scripts.
* <p>Default is "*&#47;".
* <p>Defaults to <code>"*&#47;"</code>.
* @param blockCommentEndDelimiter the end delimiter for block comments
* @return {@code this}, to facilitate method chaining
* @since 4.0.3
......
......@@ -142,16 +142,18 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
/**
* Specify the statement separator, if a custom one.
* <p>Default is ";".
* @param separator the statement separator
* <p>Defaults to {@code ";"} if not specified and falls back to {@code "\n"}
* as a last resort; may be set to {@link ScriptUtils#EOF_STATEMENT_SEPARATOR}
* to signal that each script contains a single statement without a separator.
* @param separator the script statement separator
*/
public void setSeparator(String separator) {
this.separator = separator;
}
/**
* Set the prefix that identifies line comments within the SQL scripts.
* <p>Default is "--".
* Set the prefix that identifies single-line comments within the SQL scripts.
* <p>Defaults to {@code "--"}.
* @param commentPrefix the prefix for single-line comments
*/
public void setCommentPrefix(String commentPrefix) {
......@@ -161,7 +163,7 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
/**
* Set the start delimiter that identifies block comments within the SQL
* scripts.
* <p>Default is "/*".
* <p>Defaults to {@code "/*"}.
* @param blockCommentStartDelimiter the start delimiter for block comments
* @since 4.0.3
* @see #setBlockCommentEndDelimiter
......@@ -173,7 +175,7 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
/**
* Set the end delimiter that identifies block comments within the SQL
* scripts.
* <p>Default is "*&#47;".
* <p>Defaults to <code>"*&#47;"</code>.
* @param blockCommentEndDelimiter the end delimiter for block comments
* @since 4.0.3
* @see #setBlockCommentStartDelimiter
......
......@@ -61,6 +61,17 @@ public abstract class ScriptUtils {
*/
public static final String FALLBACK_STATEMENT_SEPARATOR = "\n";
/**
* End of file (EOF) SQL statement separator.
* <p>This value may be supplied as the {@code separator} to {@link
* #executeSqlScript(Connection, EncodedResource, boolean, boolean, String, String, String, String)}
* to denote that an SQL script contains a single statement (potentially
* spanning multiple lines) with no explicit statement separator. Note that
* such a script should not actually contain this value; it is merely a
* <em>virtual</em> statement separator.
*/
public static final String EOF_STATEMENT_SEPARATOR = "<<< END OF SCRIPT >>>";
/**
* Default prefix for line comments within SQL scripts.
*/
......@@ -399,12 +410,17 @@ public abstract class ScriptUtils {
* typically "--"
* @param separator the script statement separator; defaults to
* {@value #DEFAULT_STATEMENT_SEPARATOR} if not specified and falls back to
* {@value #FALLBACK_STATEMENT_SEPARATOR} as a last resort
* {@value #FALLBACK_STATEMENT_SEPARATOR} as a last resort; may be set to
* {@value #EOF_STATEMENT_SEPARATOR} to signal that the script contains a
* single statement without a separator
* @param blockCommentStartDelimiter the <em>start</em> block comment delimiter; never
* {@code null} or empty
* @param blockCommentEndDelimiter the <em>end</em> block comment delimiter; never
* {@code null} or empty
* @throws ScriptException if an error occurred while executing the SQL script
* @see #DEFAULT_STATEMENT_SEPARATOR
* @see #FALLBACK_STATEMENT_SEPARATOR
* @see #EOF_STATEMENT_SEPARATOR
*/
public static void executeSqlScript(Connection connection, EncodedResource resource, boolean continueOnError,
boolean ignoreFailedDrops, String commentPrefix, String separator, String blockCommentStartDelimiter,
......@@ -428,7 +444,7 @@ public abstract class ScriptUtils {
if (separator == null) {
separator = DEFAULT_STATEMENT_SEPARATOR;
}
if (!containsSqlScriptDelimiters(script, separator)) {
if (!EOF_STATEMENT_SEPARATOR.equals(separator) && !containsSqlScriptDelimiters(script, separator)) {
separator = FALLBACK_STATEMENT_SEPARATOR;
}
......
......@@ -139,6 +139,17 @@ public abstract class AbstractDatabasePopulatorTests extends AbstractDatabaseIni
assertUsersDatabaseCreated("Brannen", "Hoeller");
}
@Test
public void scriptWithoutStatementSeparator() throws Exception {
databasePopulator.setSeparator(ScriptUtils.EOF_STATEMENT_SEPARATOR);
databasePopulator.addScript(resource("drop-users-schema.sql"));
databasePopulator.addScript(resource("users-schema-without-separator.sql"));
databasePopulator.addScript(resource("users-data.sql"));
DatabasePopulatorUtils.execute(databasePopulator, db);
assertUsersDatabaseCreated("Brannen");
}
@Test
public void constructorWithMultipleScriptResources() throws Exception {
final ResourceDatabasePopulator populator = new ResourceDatabasePopulator(usersSchema(),
......
INSERT INTO
users(first_name, last_name)
values('Sam', 'Brannen')
\ No newline at end of file
CREATE TABLE users (
id INTEGER NOT NULL IDENTITY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL
)
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册