@ -44,6 +44,7 @@ import org.springframework.util.StringUtils;
* @author Juergen Hoeller
* @author Juergen Hoeller
* @author Chris Beams
* @author Chris Beams
* @author Oliver Gierke
* @author Oliver Gierke
* @author Sam Brannen
* @since 3 . 0
* @since 3 . 0
* /
* /
public class ResourceDatabasePopulator implements DatabasePopulator {
public class ResourceDatabasePopulator implements DatabasePopulator {
@ -54,7 +55,6 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
private static final Log logger = LogFactory . getLog ( ResourceDatabasePopulator . class ) ;
private static final Log logger = LogFactory . getLog ( ResourceDatabasePopulator . class ) ;
private List < Resource > scripts = new ArrayList < Resource > ( ) ;
private List < Resource > scripts = new ArrayList < Resource > ( ) ;
private String sqlScriptEncoding ;
private String sqlScriptEncoding ;
@ -127,7 +127,6 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
this . ignoreFailedDrops = ignoreFailedDrops ;
this . ignoreFailedDrops = ignoreFailedDrops ;
}
}
public void populate ( Connection connection ) throws SQLException {
public void populate ( Connection connection ) throws SQLException {
for ( Resource script : this . scripts ) {
for ( Resource script : this . scripts ) {
executeSqlScript ( connection , applyEncodingIfNecessary ( script ) , this . continueOnError , this . ignoreFailedDrops ) ;
executeSqlScript ( connection , applyEncodingIfNecessary ( script ) , this . continueOnError , this . ignoreFailedDrops ) ;
@ -153,8 +152,8 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
* @param continueOnError whether or not to continue without throwing an exception in the event of an error
* @param continueOnError whether or not to continue without throwing an exception in the event of an error
* @param ignoreFailedDrops whether of not to continue in the event of specifically an error on a { @code DROP }
* @param ignoreFailedDrops whether of not to continue in the event of specifically an error on a { @code DROP }
* /
* /
private void executeSqlScript ( Connection connection , EncodedResource resource ,
private void executeSqlScript ( Connection connection , EncodedResource resource , boolean continueOnError ,
boolean continueOnError , boolean ignoreFailedDrops ) throws SQLException {
boolean ignoreFailedDrops ) throws SQLException {
if ( logger . isInfoEnabled ( ) ) {
if ( logger . isInfoEnabled ( ) ) {
logger . info ( "Executing SQL script from " + resource ) ;
logger . info ( "Executing SQL script from " + resource ) ;
@ -175,7 +174,7 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
delimiter = "\n" ;
delimiter = "\n" ;
}
}
}
}
splitSqlScript ( script , delimiter , statements ) ;
splitSqlScript ( script , delimiter , this . commentPrefix , statements ) ;
int lineNumber = 0 ;
int lineNumber = 0 ;
Statement stmt = connection . createStatement ( ) ;
Statement stmt = connection . createStatement ( ) ;
try {
try {
@ -192,8 +191,8 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
boolean dropStatement = StringUtils . startsWithIgnoreCase ( statement . trim ( ) , "drop" ) ;
boolean dropStatement = StringUtils . startsWithIgnoreCase ( statement . trim ( ) , "drop" ) ;
if ( continueOnError | | ( dropStatement & & ignoreFailedDrops ) ) {
if ( continueOnError | | ( dropStatement & & ignoreFailedDrops ) ) {
if ( logger . isDebugEnabled ( ) ) {
if ( logger . isDebugEnabled ( ) ) {
logger . debug ( "Failed to execute SQL script statement at line " + lineNumber +
logger . debug ( "Failed to execute SQL script statement at line " + lineNumber
" of resource " + resource + ": " + statement , ex ) ;
+ " of resource " + resource + ": " + statement , ex ) ;
}
}
}
}
else {
else {
@ -239,7 +238,8 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
}
}
maybeAddSeparatorToScript ( scriptBuilder ) ;
maybeAddSeparatorToScript ( scriptBuilder ) ;
return scriptBuilder . toString ( ) ;
return scriptBuilder . toString ( ) ;
} finally {
}
finally {
lnr . close ( ) ;
lnr . close ( ) ;
}
}
}
}
@ -252,7 +252,8 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
if ( trimmed . length ( ) = = this . separator . length ( ) ) {
if ( trimmed . length ( ) = = this . separator . length ( ) ) {
return ;
return ;
}
}
// separator ends in whitespace, so we might want to see if the script is trying to end the same way
// separator ends in whitespace, so we might want to see if the script is trying
// to end the same way
if ( scriptBuilder . lastIndexOf ( trimmed ) = = scriptBuilder . length ( ) - trimmed . length ( ) ) {
if ( scriptBuilder . lastIndexOf ( trimmed ) = = scriptBuilder . length ( ) - trimmed . length ( ) ) {
scriptBuilder . append ( this . separator . substring ( trimmed . length ( ) ) ) ;
scriptBuilder . append ( this . separator . substring ( trimmed . length ( ) ) ) ;
}
}
@ -270,7 +271,7 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
if ( content [ i ] = = '\'' ) {
if ( content [ i ] = = '\'' ) {
inLiteral = ! inLiteral ;
inLiteral = ! inLiteral ;
}
}
if ( ! inLiteral & & startsWithDelimiter ( script , i , delim ) ) {
if ( ! inLiteral & & script . startsWith ( delim , i ) ) {
return true ;
return true ;
}
}
}
}
@ -278,29 +279,18 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
}
}
/ * *
/ * *
* Return whether the substring of a given source { @link String } starting at the
* Split an SQL script into separate statements delimited by the provided delimiter
* given index starts with the given delimiter .
* string . Each individual statement will be added to the provided { @code List } .
* @param source the source { @link String } to inspect
* < p > Within a statement , the provided { @code commentPrefix } will be honored ;
* @param startIndex the index to look for the delimiter
* any text beginning with the comment prefix and extending to the end of the
* @param delim the delimiter to look for
* line will be omitted from the statement . In addition , multiple adjacent
* /
* whitespace characters will be collapsed into a single space .
private boolean startsWithDelimiter ( String source , int startIndex , String delim ) {
int endIndex = startIndex + delim . length ( ) ;
if ( source . length ( ) < endIndex ) {
// String is too short to contain the delimiter
return false ;
}
return source . substring ( startIndex , endIndex ) . equals ( delim ) ;
}
/ * *
* Split an SQL script into separate statements delimited with the provided delimiter
* character . Each individual statement will be added to the provided { @code List } .
* @param script the SQL script
* @param script the SQL script
* @param delim character delimiting each statement ( typically a ';' character )
* @param delim character delimiting each statement ( typically a ';' character )
* @param commentPrefix the prefix that identifies line comments in the SQL script & mdash ; typically "--"
* @param statements the List that will contain the individual statements
* @param statements the List that will contain the individual statements
* /
* /
private void splitSqlScript ( String script , String delim , List < String > statements ) {
private void splitSqlScript ( String script , String delim , String commentPrefix , List < String > statements ) {
StringBuilder sb = new StringBuilder ( ) ;
StringBuilder sb = new StringBuilder ( ) ;
boolean inLiteral = false ;
boolean inLiteral = false ;
boolean inEscape = false ;
boolean inEscape = false ;
@ -322,7 +312,8 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
inLiteral = ! inLiteral ;
inLiteral = ! inLiteral ;
}
}
if ( ! inLiteral ) {
if ( ! inLiteral ) {
if ( startsWithDelimiter ( script , i , delim ) ) {
if ( script . startsWith ( delim , i ) ) {
// we've reached the end of the current statement
if ( sb . length ( ) > 0 ) {
if ( sb . length ( ) > 0 ) {
statements . add ( sb . toString ( ) ) ;
statements . add ( sb . toString ( ) ) ;
sb = new StringBuilder ( ) ;
sb = new StringBuilder ( ) ;
@ -330,8 +321,27 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
i + = delim . length ( ) - 1 ;
i + = delim . length ( ) - 1 ;
continue ;
continue ;
}
}
else if ( c = = '\n' | | c = = '\t' ) {
else if ( script . startsWith ( commentPrefix , i ) ) {
c = ' ' ;
// skip over any content from the start of the comment to the EOL
int indexOfNextNewline = script . indexOf ( "\n" , i ) ;
if ( indexOfNextNewline > i ) {
i = indexOfNextNewline ;
continue ;
}
else {
// if there's no newline after the comment, we must be at the end
// of the script, so stop here.
break ;
}
}
else if ( c = = ' ' | | c = = '\n' | | c = = '\t' ) {
// avoid multiple adjacent whitespace characters
if ( sb . length ( ) > 0 & & sb . charAt ( sb . length ( ) - 1 ) ! = ' ' ) {
c = ' ' ;
}
else {
continue ;
}
}
}
}
}
sb . append ( c ) ;
sb . append ( c ) ;