Skip to content

Commit ec2df7d

Browse files
committed
Merge pull request #143 from olivergierke/SPR-9781
# By Oliver Gierke * SPR-9781: Work around JDK7 String#substring performance regression
2 parents dfe0530 + 3fb3b7d commit ec2df7d

File tree

3 files changed

+2057
-5
lines changed

3 files changed

+2057
-5
lines changed

spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ResourceDatabasePopulator.java

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2011 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -43,6 +43,7 @@
4343
* @author Dave Syer
4444
* @author Juergen Hoeller
4545
* @author Chris Beams
46+
* @author Oliver Gierke
4647
* @since 3.0
4748
*/
4849
public class ResourceDatabasePopulator implements DatabasePopulator {
@@ -265,16 +266,37 @@ private boolean containsSqlScriptDelimiters(String script, String delim) {
265266
if (content[i] == '\'') {
266267
inLiteral = !inLiteral;
267268
}
268-
if (!inLiteral && script.substring(i).startsWith(delim)) {
269+
if (!inLiteral && startsWithDelimiter(script, i, delim)) {
269270
return true;
270271
}
271272
}
272273
return false;
273274
}
274275

275276
/**
276-
* Split an SQL script into separate statements delimited with the provided delimiter character.
277-
* Each individual statement will be added to the provided <code>List</code>.
277+
* Return whether the substring of a given source {@link String} starting at the
278+
* given index starts with the given delimiter.
279+
*
280+
* @param source the source {@link String} to inspect
281+
* @param startIndex the index to look for the delimiter
282+
* @param delim the delimiter to look for
283+
*/
284+
private boolean startsWithDelimiter(String source, int startIndex, String delim) {
285+
286+
int endIndex = startIndex + delim.length();
287+
288+
if (source.length() < endIndex) {
289+
// String is too short to contain the delimiter
290+
return false;
291+
}
292+
293+
return source.substring(startIndex, endIndex).equals(delim);
294+
}
295+
296+
/**
297+
* Split an SQL script into separate statements delimited with the provided delimiter
298+
* character. Each individual statement will be added to the provided {@code List}.
299+
*
278300
* @param script the SQL script
279301
* @param delim character delimiting each statement (typically a ';' character)
280302
* @param statements the List that will contain the individual statements
@@ -301,7 +323,7 @@ private void splitSqlScript(String script, String delim, List<String> statements
301323
inLiteral = !inLiteral;
302324
}
303325
if (!inLiteral) {
304-
if (script.substring(i).startsWith(delim)) {
326+
if (startsWithDelimiter(script, i, delim)) {
305327
if (sb.length() > 0) {
306328
statements.add(sb.toString());
307329
sb = new StringBuilder();

spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/DatabasePopulatorTests.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,4 +238,21 @@ public void usesBoundConnectionIfAvailable() throws SQLException {
238238

239239
EasyMock.verify(populator);
240240
}
241+
242+
/**
243+
* @see SPR-9781
244+
*/
245+
@Test(timeout = 1000)
246+
public void executesHugeScriptInReasonableTime() throws SQLException {
247+
248+
databasePopulator.addScript(resourceLoader.getResource("db-schema.sql"));
249+
databasePopulator.addScript(resourceLoader.getResource("db-test-data-huge.sql"));
250+
251+
Connection connection = db.getConnection();
252+
try {
253+
databasePopulator.populate(connection);
254+
} finally {
255+
connection.close();
256+
}
257+
}
241258
}

0 commit comments

Comments
 (0)